#!/usr/bin/python # Copyright (c) 2014-2017 Ansible Project # Copyright (c) 2017, 2018 Will Thames # Copyright (c) 2017, 2018 Michael De La Rue # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) ANSIBLE_METADATA = {'status': ['preview'], 'supported_by': 'community', 'metadata_version': '1.1'} DOCUMENTATION = ''' --- module: rds_snapshot_facts version_added: "2.6" short_description: obtain facts about one or more RDS snapshots description: - obtain facts about one or more RDS snapshots. These can be for unclustered snapshots or snapshots of clustered DBs (Aurora) - Aurora snapshot facts may be obtained if no identifier parameters are passed or if one of the cluster parameters are passed. options: db_snapshot_identifier: description: - Name of an RDS (unclustered) snapshot. Mutually exclusive with I(db_instance_identifier), I(db_cluster_identifier), I(db_cluster_snapshot_identifier) required: false aliases: - snapshot_name db_instance_identifier: description: - RDS instance name for which to find snapshots. Mutually exclusive with I(db_snapshot_identifier), I(db_cluster_identifier), I(db_cluster_snapshot_identifier) required: false db_cluster_identifier: description: - RDS cluster name for which to find snapshots. Mutually exclusive with I(db_snapshot_identifier), I(db_instance_identifier), I(db_cluster_snapshot_identifier) required: false db_cluster_snapshot_identifier: description: - Name of an RDS cluster snapshot. Mutually exclusive with I(db_instance_identifier), I(db_snapshot_identifier), I(db_cluster_identifier) required: false snapshot_type: description: - Type of snapshot to find. By default both automated and manual snapshots will be returned. required: false choices: ['automated', 'manual', 'shared', 'public'] requirements: - "python >= 2.6" - "boto3" author: - "Will Thames (@willthames)" extends_documentation_fragment: - aws - ec2 ''' EXAMPLES = ''' # Get facts about an snapshot - rds_snapshot_facts: db_snapshot_identifier: snapshot_name register: new_database_facts # Get all RDS snapshots for an RDS instance - rds_snapshot_facts: db_instance_identifier: helloworld-rds-master ''' RETURN = ''' snapshots: description: List of non-clustered snapshots returned: When cluster parameters are not passed type: complex contains: allocated_storage: description: How many gigabytes of storage are allocated returned: always type: int sample: 10 availability_zone: description: The availability zone of the database from which the snapshot was taken returned: always type: string sample: us-west-2b db_instance_identifier: description: Database instance identifier returned: always type: string sample: hello-world-rds db_snapshot_arn: description: Snapshot ARN returned: always type: string sample: arn:aws:rds:us-west-2:111111111111:snapshot:rds:hello-world-rds-us1-2018-05-16-04-03 db_snapshot_identifier: description: Snapshot name returned: always type: string sample: rds:hello-world-rds-us1-2018-05-16-04-03 encrypted: description: Whether the snapshot was encrypted returned: always type: bool sample: true engine: description: Database engine returned: always type: string sample: postgres engine_version: description: Database engine version returned: always type: string sample: 9.5.10 iam_database_authentication_enabled: description: Whether database authentication through IAM is enabled returned: always type: bool sample: false instance_create_time: description: Time the Instance was created returned: always type: string sample: '2017-10-10T04:00:07.434000+00:00' kms_key_id: description: ID of the KMS Key encrypting the snapshot returned: always type: string sample: arn:aws:kms:us-west-2:111111111111:key/abcd1234-1234-aaaa-0000-1234567890ab license_model: description: License model returned: always type: string sample: postgresql-license master_username: description: Database master username returned: always type: string sample: dbadmin option_group_name: description: Database option group name returned: always type: string sample: default:postgres-9-5 percent_progress: description: Perecent progress of snapshot returned: always type: int sample: 100 snapshot_create_time: description: Time snapshot was created returned: always type: string sample: '2018-05-16T04:03:33.871000+00:00' snapshot_type: description: Type of snapshot returned: always type: string sample: automated status: description: Status of snapshot returned: always type: string sample: available storage_type: description: Storage type of underlying DB returned: always type: string sample: gp2 tags: description: Snapshot tags returned: always type: complex contains: {} vpc_id: description: ID of VPC containing the DB returned: always type: string sample: vpc-abcd1234 cluster_snapshots: description: List of cluster snapshots returned: always type: complex contains: allocated_storage: description: How many gigabytes of storage are allocated returned: always type: int sample: 1 availability_zones: description: The availability zones of the database from which the snapshot was taken returned: always type: list sample: - ca-central-1a - ca-central-1b cluster_create_time: description: Date and time the cluster was created returned: always type: string sample: '2018-05-17T00:13:40.223000+00:00' db_cluster_identifier: description: Database cluster identifier returned: always type: string sample: test-aurora-cluster db_cluster_snapshot_arn: description: ARN of the database snapshot returned: always type: string sample: arn:aws:rds:ca-central-1:111111111111:cluster-snapshot:test-aurora-snapshot db_cluster_snapshot_identifier: description: Snapshot identifier returned: always type: string sample: test-aurora-snapshot engine: description: Database engine returned: always type: string sample: aurora engine_version: description: Database engine version returned: always type: string sample: 5.6.10a iam_database_authentication_enabled: description: Whether database authentication through IAM is enabled returned: always type: bool sample: false kms_key_id: description: ID of the KMS Key encrypting the snapshot returned: always type: string sample: arn:aws:kms:ca-central-1:111111111111:key/abcd1234-abcd-1111-aaaa-0123456789ab license_model: description: License model returned: always type: string sample: aurora master_username: description: Database master username returned: always type: string sample: shertel percent_progress: description: Perecent progress of snapshot returned: always type: int sample: 0 port: description: Database port returned: always type: int sample: 0 snapshot_create_time: description: Date and time when the snapshot was created returned: always type: string sample: '2018-05-17T00:23:23.731000+00:00' snapshot_type: description: Type of snapshot returned: always type: string sample: manual status: description: Status of snapshot returned: always type: string sample: creating storage_encrypted: description: Whether the snapshot is encrypted returned: always type: bool sample: true tags: description: Tags of the snapshot returned: always type: complex contains: {} vpc_id: description: VPC of the database returned: always type: string sample: vpc-abcd1234 ''' from ansible.module_utils.aws.core import AnsibleAWSModule, is_boto3_error_code from ansible.module_utils.ec2 import AWSRetry, boto3_tag_list_to_ansible_dict, camel_dict_to_snake_dict try: import botocore except BaseException: pass # caught by imported HAS_BOTO3 def common_snapshot_facts(module, conn, method, prefix, params): paginator = conn.get_paginator(method) try: results = paginator.paginate(**params).build_full_result()['%ss' % prefix] except is_boto3_error_code('%sNotFound' % prefix): results = [] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except module.fail_json_aws(e, "trying to get snapshot information") for snapshot in results: try: snapshot['Tags'] = boto3_tag_list_to_ansible_dict(conn.list_tags_for_resource(ResourceName=snapshot['%sArn' % prefix], aws_retry=True)['TagList']) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, "Couldn't get tags for snapshot %s" % snapshot['%sIdentifier' % prefix]) return [camel_dict_to_snake_dict(snapshot, ignore_list=['Tags']) for snapshot in results] def cluster_snapshot_facts(module, conn): snapshot_name = module.params.get('db_cluster_snapshot_identifier') snapshot_type = module.params.get('snapshot_type') instance_name = module.params.get('db_cluster_instance_identifier') params = dict() if snapshot_name: params['DBClusterSnapshotIdentifier'] = snapshot_name if instance_name: params['DBClusterInstanceIdentifier'] = instance_name if snapshot_type: params['SnapshotType'] = snapshot_type if snapshot_type == 'public': params['IsPublic'] = True elif snapshot_type == 'shared': params['IsShared'] = True return common_snapshot_facts(module, conn, 'describe_db_cluster_snapshots', 'DBClusterSnapshot', params) def standalone_snapshot_facts(module, conn): snapshot_name = module.params.get('db_snapshot_identifier') snapshot_type = module.params.get('snapshot_type') instance_name = module.params.get('db_instance_identifier') params = dict() if snapshot_name: params['DBSnapshotIdentifier'] = snapshot_name if instance_name: params['DBInstanceIdentifier'] = instance_name if snapshot_type: params['SnapshotType'] = snapshot_type if snapshot_type == 'public': params['IsPublic'] = True elif snapshot_type == 'shared': params['IsShared'] = True return common_snapshot_facts(module, conn, 'describe_db_snapshots', 'DBSnapshot', params) def main(): argument_spec = dict( db_snapshot_identifier=dict(aliases=['snapshot_name']), db_instance_identifier=dict(), db_cluster_identifier=dict(), db_cluster_snapshot_identifier=dict(), snapshot_type=dict(choices=['automated', 'manual', 'shared', 'public']) ) module = AnsibleAWSModule( argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=[['db_snapshot_identifier', 'db_instance_identifier', 'db_cluster_identifier', 'db_cluster_snapshot_identifier']] ) conn = module.client('rds', retry_decorator=AWSRetry.jittered_backoff(retries=10)) results = dict() if not module.params['db_cluster_identifier'] and not module.params['db_cluster_snapshot_identifier']: results['snapshots'] = standalone_snapshot_facts(module, conn) if not module.params['db_snapshot_identifier'] and not module.params['db_instance_identifier']: results['cluster_snapshots'] = cluster_snapshot_facts(module, conn) module.exit_json(changed=False, **results) if __name__ == '__main__': main()