diff --git a/changelogs/fragments/512-ec2_snapshot_add_check_mode_support.yml.yml b/changelogs/fragments/512-ec2_snapshot_add_check_mode_support.yml.yml new file mode 100644 index 00000000000..acc069ad913 --- /dev/null +++ b/changelogs/fragments/512-ec2_snapshot_add_check_mode_support.yml.yml @@ -0,0 +1,3 @@ +minor_changes: + - ec2_snapshot - add check_mode support + (https://github.com/ansible-collections/amazon.aws/pull/512). diff --git a/plugins/modules/ec2_snapshot.py b/plugins/modules/ec2_snapshot.py index 317b1c7c507..852102457de 100644 --- a/plugins/modules/ec2_snapshot.py +++ b/plugins/modules/ec2_snapshot.py @@ -71,12 +71,10 @@ required: false default: 0 type: int - author: "Will Thames (@willthames)" extends_documentation_fragment: - amazon.aws.aws - amazon.aws.ec2 - ''' EXAMPLES = ''' @@ -288,6 +286,9 @@ def create_snapshot(module, ec2, description=None, wait=None, 'Tags': ansible_dict_to_boto3_tag_list(_tags), }] try: + if module.check_mode: + module.exit_json(changed=True, msg='Would have created a snapshot if not in check mode', + volume_id=volume['VolumeId'], volume_size=volume['Size']) snapshot = _create_snapshot(ec2, **params) except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: module.fail_json_aws(e, msg="Failed to create snapshot") @@ -321,6 +322,12 @@ def create_snapshot(module, ec2, description=None, wait=None, def delete_snapshot(module, ec2, snapshot_id): + if module.check_mode: + try: + _describe_snapshots(ec2, SnapshotIds=[(snapshot_id)]) + module.exit_json(changed=True, msg='Would have deleted snapshot if not in check mode') + except is_boto3_error_code('InvalidSnapshot.NotFound'): + module.exit_json(changed=False, msg='Invalid snapshot ID - snapshot not found') try: ec2.delete_snapshot(aws_retry=True, SnapshotId=snapshot_id) except is_boto3_error_code('InvalidSnapshot.NotFound'): @@ -364,6 +371,7 @@ def create_snapshot_ansible_module(): required_if=required_if, required_one_of=required_one_of, required_together=required_together, + supports_check_mode=True, ) return module diff --git a/tests/integration/targets/ec2_snapshot/tasks/main.yml b/tests/integration/targets/ec2_snapshot/tasks/main.yml index 6866789df78..63fadd60d38 100644 --- a/tests/integration/targets/ec2_snapshot/tasks/main.yml +++ b/tests/integration/targets/ec2_snapshot/tasks/main.yml @@ -9,9 +9,6 @@ # Tests ec2_snapshot_info: # - Listing snapshots for filter: tag # -# Possible Bugs: -# - check_mode not supported -# - name: Integration testing for ec2_snapshot module_defaults: group/aws: @@ -23,7 +20,6 @@ collections: - community.aws - block: - name: Gather availability zones aws_az_facts: @@ -48,17 +44,18 @@ - untagged_snapshot.snapshots| length == 1 - untagged_snapshot.snapshots[0].volume_id == volume_detached.volume_id - - name: Setup an instance for testing + - name: Setup an instance for testing, make sure volumes are attached before next task ec2_instance: name: '{{ resource_prefix }}' instance_type: t2.nano image_id: '{{ ec2_ami_id }}' - wait: yes volumes: - device_name: /dev/xvda ebs: volume_size: 8 delete_on_termination: true + state: running + wait: true register: instance - set_fact: @@ -66,17 +63,18 @@ instance_id: '{{ instance.instances[0].instance_id }}' device_name: '{{ instance.instances[0].block_device_mappings[0].device_name }}' -# JR: Check mode not supported -# - name: Take snapshot (check mode) -# ec2_snapshot: -# instance_id: '{{ instance_id }}' -# check_mode: true -# snapshot_tags: -# Test: '{{ resource_prefix }}' -# register: result -# - assert: -# that: -# - result is changed + - name: Take snapshot (check mode) + ec2_snapshot: + instance_id: '{{ instance_id }}' + device_name: '{{ device_name }}' + snapshot_tags: + Test: '{{ resource_prefix }}' + check_mode: true + register: result + + - assert: + that: + - result is changed - name: Take snapshot of volume ec2_snapshot: @@ -105,7 +103,7 @@ filters: "tag:Name": '{{ resource_prefix }}' register: info_check - check_mode: yes + check_mode: true - assert: that: @@ -116,18 +114,17 @@ - info_check.snapshots[0].volume_size == result.volume_size - info_check.snapshots[0].tags == result.tags -# JR: Check mode not supported -# - name: Take snapshot if most recent >1hr (False) (check mode) -# ec2_snapshot: -# volume_id: '{{ volume_id }}' -# snapshot_tags: -# Name: '{{ resource_prefix }}' -# last_snapshot_min_age: 60 -# check_mode: true -# register: result -# - assert: -# that: -# - result is not changed + - name: Take snapshot if most recent >1hr (False) (check mode) + ec2_snapshot: + volume_id: '{{ volume_id }}' + snapshot_tags: + Name: '{{ resource_prefix }}' + last_snapshot_min_age: 60 + check_mode: true + register: result + - assert: + that: + - result is not changed - name: Take snapshot if most recent >1hr (False) ec2_snapshot: @@ -150,18 +147,17 @@ pause: minutes: 1 -# JR: Check mode not supported -# - name: Take snapshot if most recent >1min (True) (check mode) -# ec2_snapshot: -# volume_id: '{{ volume_id }}' -# snapshot_tags: -# Name: '{{ resource_prefix }}' -# last_snapshot_min_age: 1 -# check_mode: true -# register: result -# - assert: -# that: -# - result is changed + - name: Take snapshot if most recent >1min (True) (check mode) + ec2_snapshot: + volume_id: '{{ volume_id }}' + snapshot_tags: + Name: '{{ resource_prefix }}' + last_snapshot_min_age: 1 + check_mode: true + register: result + - assert: + that: + - result is changed - name: Take snapshot if most recent >1min (True) ec2_snapshot: @@ -181,16 +177,16 @@ - info_result.snapshots| length == 2 - result.snapshot_id in ( info_result.snapshots | map(attribute='snapshot_id') | list ) -# JR: Check mode not supported -# - name: Take snapshot with a tag (check mode) -# ec2_snapshot: -# volume_id: '{{ volume_id }}' -# snapshot_tags: -# MyTag: '{{ resource_prefix }}' -# register: result -# - assert: -# that: -# - result is changed + - name: Take snapshot with a tag (check mode) + ec2_snapshot: + volume_id: '{{ volume_id }}' + snapshot_tags: + MyTag: '{{ resource_prefix }}' + check_mode: true + register: result + - assert: + that: + - result is changed - name: Take snapshot and tag it ec2_snapshot: @@ -224,9 +220,10 @@ - assert: that: - - info_result.snapshots| length == 3 + - info_result.snapshots | length == 3 - - ec2_snapshot: + - name: Generate extra snapshots + ec2_snapshot: volume_id: '{{ volume_id }}' snapshot_tags: ResourcePrefix: '{{ resource_prefix }}' @@ -295,12 +292,46 @@ that: - info_result.snapshots | length == 3 + # delete the tagged snapshot - check mode + - name: Delete the tagged snapshot (check mode) + ec2_snapshot: + state: absent + snapshot_id: '{{ tagged_snapshot_id }}' + register: delete_result_check_mode + check_mode: true + + - assert: + that: + - delete_result_check_mode is changed + # delete the tagged snapshot - name: Delete the tagged snapshot ec2_snapshot: state: absent snapshot_id: '{{ tagged_snapshot_id }}' + # delete the tagged snapshot again (results in InvalidSnapshot.NotFound) + - name: Delete already removed snapshot (check mode) + ec2_snapshot: + state: absent + snapshot_id: '{{ tagged_snapshot_id }}' + register: delete_result_second_check_mode + check_mode: true + + - assert: + that: + - delete_result_second_check_mode is not changed + + - name: Delete already removed snapshot (idempotent) + ec2_snapshot: + state: absent + snapshot_id: '{{ tagged_snapshot_id }}' + register: delete_result_second_idempotent + + - assert: + that: + - delete_result_second_idempotent is not changed + - name: Get info about all snapshots for this test ec2_snapshot_info: filters: