Exemple #1
0
    def setUpClass(cls):
        if not sys.warnoptions:
            import warnings
            warnings.simplefilter("ignore")

        cls.logger = ConsoleLogger()

        cls.task_runner = get_task_runner(TESTED_ACTION,
                                          KEEP_AND_USE_EXISTING_ACTION_STACK)

        cls.resource_stack = get_resource_stack(
            TESTED_ACTION,
            create_resource_stack_func=cls.create_resource_stack,
            use_existing=KEEP_AND_USE_EXISTING_RESOURCES_STACK,
            region_name=region())

        assert (cls.resource_stack is not None)

        cls.ec2 = Ec2(region())

        cls.volume_unencrypted = cls.resource_stack.stack_outputs[
            "VolumeIdEncryptedUnencrypted"]
        cls.volume_encrypted_default = cls.resource_stack.stack_outputs[
            "VolumeIdEncryptedDefault"]
        cls.volume_encrypted_custom = cls.resource_stack.stack_outputs[
            "VolumeIdEncryptedCustom"]
        cls.custom_key_arn = cls.resource_stack.stack_outputs[
            "EncryptionKeyArn"]
    def setUpClass(cls):

        cls.ec2 = Ec2(region())
        cls.elb = Elb(region())
        cls.elbv2 = ElbV2(region())
        cls.logger = ConsoleLogger()

        cls.resource_stack = get_resource_stack(TESTED_ACTION,
                                                create_resource_stack_func=cls.create_resource_stack,
                                                use_existing=KEEP_AND_USE_EXISTING_RESOURCES_STACK,
                                                region_name=region())

        assert (cls.resource_stack is not None)

        cls.v1_elb_name = cls.resource_stack.stack_outputs["V1LoadBalancerName"]
        cls.v2_target_group_arn = cls.resource_stack.stack_outputs["V2TargetGroupArn"]
        cls.instance_profile = cls.resource_stack.stack_outputs["InstanceProfile"]

        # noinspection PyPep8,PyBroadException
        try:
            cls.ec2.ec2_service.get(services.ec2_service.KEY_PAIRS, KeyNames=[TESTED_ACTION], region=region())
            cls.key_pair = TESTED_ACTION
        except:
            cls.key_pair = cls.ec2.ec2_client.create_key_pair(KeyName=TESTED_ACTION).get("KeyName")

        cls.ami_single_volume = cls.ec2.latest_aws_linux_image["ImageId"]

        cls.task_runner = get_task_runner(TESTED_ACTION, KEEP_AND_USE_EXISTING_ACTION_STACK)
Exemple #3
0
    def setUpClass(cls):
        if not sys.warnoptions:
            import warnings
            warnings.simplefilter("ignore")

        cls.logger = ConsoleLogger()

        cls.resource_stack = get_resource_stack(
            TESTED_ACTION,
            create_resource_stack_func=cls.create_resource_stack,
            use_existing=KEEP_AND_USE_EXISTING_RESOURCES_STACK,
            region_name=region())
        assert (cls.resource_stack is not None)

        cls.instance_id = cls.resource_stack.stack_outputs["InstanceId0"]
        cls.root_volume = Ec2(region()).get_root_volume(cls.instance_id)
        cls.data_volumes = [
            cls.resource_stack.stack_outputs["VolumeId0"],
            cls.resource_stack.stack_outputs["VolumeId1"]
        ]

        cls.task_runner = get_task_runner(TESTED_ACTION,
                                          KEEP_AND_USE_EXISTING_ACTION_STACK)

        cls.ec2 = Ec2(region())
Exemple #4
0
    def setUpClass(cls):
        if not sys.warnoptions:
            import warnings
            warnings.simplefilter("ignore")

        cls.logger = ConsoleLogger()

        cls.resource_stack = get_resource_stack(
            TESTED_ACTION,
            create_resource_stack_func=cls.create_resource_stack,
            use_existing=KEEP_AND_USE_EXISTING_RESOURCES_STACK,
            region_name=region())
        assert (cls.resource_stack is not None)

        cls.instance_no_cpu_load = cls.resource_stack.stack_outputs[
            "InstanceNoCPULoad"]
        cls.instance_cpu_load = cls.resource_stack.stack_outputs[
            "InstanceCPULoad"]

        cls.task_runner = get_task_runner(
            TESTED_ACTION,
            KEEP_AND_USE_EXISTING_ACTION_STACK,
            interval="0/{} * * * ?".format(INTERVAL_MINUTES))

        cls.ec2 = Ec2(region())

        testing.tags.set_ec2_tag_to_delete(
            ec2_client=cls.ec2,
            resource_ids=[cls.instance_no_cpu_load, cls.instance_cpu_load])

        cls.metrics_client = CloudwatchMetrics(region())
Exemple #5
0
    def setUpClass(cls):
        if not sys.warnoptions:
            import warnings
            warnings.simplefilter("ignore")

        cls.logger = ConsoleLogger()

        cls.resource_stack = get_resource_stack(
            TESTED_ACTION,
            create_resource_stack_func=cls.create_resource_stack,
            use_existing=KEEP_AND_USE_EXISTING_RESOURCES_STACK,
            region_name=region())

        assert (cls.resource_stack is not None)

        cls.ec2 = Ec2(region())
        cls.instance_id = cls.resource_stack.stack_outputs["InstanceId"]
        if KEEP_AND_USE_EXISTING_ACTION_STACK:
            cls.ec2.start_instance(cls.instance_id)

        testing.tags.set_ec2_tag_to_delete(ec2_client=cls.ec2,
                                           resource_ids=[cls.instance_id])

        cls.task_runner = get_task_runner(TESTED_ACTION,
                                          KEEP_AND_USE_EXISTING_ACTION_STACK)

        tags = cls.ec2.get_instance_tags(cls.instance_id)
        cls.original_tags = {
            t: tags[t]
            for t in tags if not t.startswith("aws:")
        }
Exemple #6
0
    def test_copy_unencrypted_snapshot_same_region(self):

        test_method = inspect.stack()[0][3]

        self.cleanup_leftover_source_snapshots(test_method)

        self.logger.test("Creating source snapshot")
        source_snapshot_unencrypted = self.ec2.create_snapshot(self.volume_unencrypted, tags={
            "copied-tag": "copied-value",
            "not-copied-tag": "not-copied-value",
            "Name": "Ec2CopySnapshot_{}".format(test_method),
            tasklist_tagname(TESTED_ACTION): test_method
        }, description="Snapshot for testing Ec2CopySnapshot : {}".format(test_method))
        self.snapshots.append(source_snapshot_unencrypted["SnapshotId"])

        testing.tags.set_ec2_tag_to_delete(self.ec2, [source_snapshot_unencrypted["SnapshotId"]])

        parameters = {
            copy_snapshot.PARAM_DESTINATION_REGION: region(),
            copy_snapshot.PARAM_ACCOUNTS_VOLUME_CREATE_PERMISSIONS: ["123456789012"],
            copy_snapshot.PARAM_COPIED_SNAPSHOT_TAGS: "copied-tag",
            copy_snapshot.PARAM_SNAPSHOT_DESCRIPTION: "{{{}}}".format(copy_snapshot.TAG_PLACEHOLDER_SOURCE_DESCRIPTION),
            copy_snapshot.PARAM_SNAPSHOT_TAGS: testing.tags.common_placeholder_tags(
                test_delete=False,
                placeholders=[
                    copy_snapshot.TAG_PLACEHOLDER_SOURCE_REGION,
                    copy_snapshot.TAG_PLACEHOLDER_SOURCE_SNAPSHOT_ID,
                    copy_snapshot.TAG_PLACEHOLDER_SOURCE_VOLUME,
                    copy_snapshot.TAG_PLACEHOLDER_OWNER_ACCOUNT]),
            copy_snapshot.PARAM_SOURCE_TAGS: testing.tags.common_placeholder_tags([
                copy_snapshot.TAG_PLACEHOLDER_COPIED_SNAPSHOT_ID,
                copy_snapshot.TAG_PLACEHOLDER_COPIED_REGION
            ]),
            copy_snapshot.PARAM_COPIED_SNAPSHOTS: copy_snapshot.COPIED_OWNED_BY_ACCOUNT,
            copy_snapshot.PARAM_DELETE_AFTER_COPY: False,
            copy_snapshot.PARAM_ENCRYPTED: False
        }

        self.logger.test("Running task")
        self.task_runner.run(parameters,
                             task_name=test_method,
                             complete_check_polling_interval=10)
        self.assertTrue(self.task_runner.success(), "Task executed successfully")
        snapshot_copy_id = self.task_runner.results[0].result["copy-snapshot-id"]
        self.snapshots.append(snapshot_copy_id)
        self.logger.test("[X] Task completed")

        self.check_copy_snapshot(snapshot_copy_id, source_snapshot_unencrypted, region())
        self.check_source_snapshot(source_snapshot_unencrypted["SnapshotId"], snapshot_copy_id, test_method, region())

        assert (self.task_runner.max_concurrency == 5)
        assert (self.task_runner.concurrency_key == "ec2:CopySnapshot:{}:{}".format(self.task_runner.tested_account,
                                                                                    self.task_runner.tested_region))
Exemple #7
0
    def test_copy_snapshot_encrypted_with_default_key(self):

        test_method = inspect.stack()[0][3]

        self.cleanup_leftover_source_snapshots(test_method)

        snapshot_unencrypted = self.ec2.create_snapshot(self.volume_unencrypted, tags={
            "Name": "Ec2CopySnapshot_{}".format(test_method),
            tasklist_tagname(TESTED_ACTION): test_method
        }, description="Snapshot for testing Ec2CopySnapshot : {}".format(test_method))
        assert (snapshot_unencrypted is not None)
        self.snapshots.append(snapshot_unencrypted["SnapshotId"])

        parameters = {
            copy_snapshot.PARAM_DESTINATION_REGION: region(),
            copy_snapshot.PARAM_ENCRYPTED: True
        }

        self.logger.test("Running task")
        self.task_runner.run(parameters,
                             task_name=test_method,
                             complete_check_polling_interval=10)
        self.assertTrue(self.task_runner.success(), "Task executed successfully")
        snapshot_copy_id = self.task_runner.results[0].result["copy-snapshot-id"]
        self.snapshots.append(snapshot_copy_id)
        self.logger.test("[X] Task completed")

        self.logger.test("Checking snapshot copy")
        snapshot_copy = self.ec2.get_snapshot(snapshot_copy_id)
        self.assertIsNotNone(snapshot_copy, "Snapshot created")
        self.assertTrue(snapshot_copy["Encrypted"], "Snapshot is encrypted")
        self.assertEqual(snapshot_copy["KmsKeyId"], self.ec2.ebs_default_key_arn, "Default EBS encryption key is used")
        self.logger.test("[X] Snapshot created and encrypted")
Exemple #8
0
    def test_snapshot_not_longer_available(self):

        def delete_snapshot_after_select(tracker):
            for item in tracker.task_items:
                self.ec2.delete_snapshots(snapshot_ids=[item.get(handlers.TASK_TR_RESOURCES, {}).get("SnapshotId")])

        test_method = inspect.stack()[0][3]

        self.cleanup_leftover_source_snapshots(test_method)

        self.logger.test("Creating source snapshot")
        source_snapshot = self.ec2.create_snapshot(self.volume_unencrypted, tags={
            "Name": "Ec2CopySnapshot_{}".format(test_method),
            tasklist_tagname(TESTED_ACTION): test_method
        }, description="Snapshot for testing Ec2CopySnapshot : {}".format(test_method))
        assert (source_snapshot is not None)
        self.snapshots.append(source_snapshot["SnapshotId"])

        parameters = {
            copy_snapshot.PARAM_DESTINATION_REGION: region(),
        }

        self.logger.test("Running task to copy snapshot")
        self.task_runner.run(parameters,
                             task_name=test_method,
                             complete_check_polling_interval=10, run_after_select=delete_snapshot_after_select)

        self.logger.test("[X] Task completed")
        self.assertEqual(1, len(self.task_runner.results), "Snapshot not longer available")
        self.logger.test("[X] Snapshot was not longer available")
Exemple #9
0
    def test_snapshot_only_copied_once(self):

        test_method = inspect.stack()[0][3]

        self.cleanup_leftover_source_snapshots(test_method)

        self.logger.test("Creating source snapshot")
        source_snapshot = self.ec2.create_snapshot(self.volume_unencrypted, tags={
            "Name": "Ec2CopySnapshot_{}".format(test_method),
            tasklist_tagname(TESTED_ACTION): test_method
        }, description="Snapshot for testing Ec2CopySnapshot : {}".format(test_method))
        assert (source_snapshot is not None)
        self.snapshots.append(source_snapshot["SnapshotId"])

        parameters = {
            copy_snapshot.PARAM_DESTINATION_REGION: region(),
        }

        self.logger.test("Running task to copy snapshot")
        self.task_runner.run(parameters,
                             task_name=test_method,
                             complete_check_polling_interval=10)
        self.assertTrue(self.task_runner.success(), "Task executed successfully")
        snapshot_copy_id = self.task_runner.results[0].result["copy-snapshot-id"]
        self.snapshots.append(snapshot_copy_id)

        self.logger.test("Running task again")
        self.task_runner.run(parameters, task_name=test_method, complete_check_polling_interval=10)
        self.logger.test("[X] Task completed")
        self.assertEqual(0, len(self.task_runner.results), "Snapshot already copied")
        self.logger.test("[X] Snapshot was not copied for second time")
Exemple #10
0
    def test_copy_snapshot_description(self):

        test_method = inspect.stack()[0][3]

        self.cleanup_leftover_source_snapshots(test_method)

        self.logger.test("Creating source snapshot")
        source_snapshot = self.ec2.create_snapshot(self.volume_unencrypted,
                                                   tags={
                                                       "Name": "Ec2CopySnapshot_{}".format(test_method),
                                                       tasklist_tagname(TESTED_ACTION): test_method
                                                   }, description="Snapshot for testing Ec2CopySnapshot : {}".format(test_method))
        self.snapshots.append(source_snapshot["SnapshotId"])

        parameters = {
            copy_snapshot.PARAM_DESTINATION_REGION: region(),
            copy_snapshot.PARAM_COPIED_SNAPSHOTS: copy_snapshot.COPIED_OWNED_BY_ACCOUNT,
            copy_snapshot.PARAM_DELETE_AFTER_COPY: False,
            copy_snapshot.PARAM_ENCRYPTED: False
        }

        self.logger.test("Running task")
        self.task_runner.run(parameters,
                             task_name=test_method,
                             complete_check_polling_interval=10)
        self.assertTrue(self.task_runner.success(), "Task executed successfully")
        snapshot_copy_id = self.task_runner.results[0].result["copy-snapshot-id"]
        self.snapshots.append(snapshot_copy_id)
        self.logger.test("[X] Task completed")

        copied_snapshot = self.ec2.get_snapshot(snapshot_copy_id)
        self.assertEqual(source_snapshot.get("Description"), copied_snapshot.get("Description"), "Description copied as default")
        self.logger.test("[X]Source description copied")
Exemple #11
0
 def create_resource_stack(cls, resource_stack_name):
     try:
         cls.logger.test("Creating test resources stack {}", resource_stack_name)
         ami = Ec2(region()).latest_aws_linux_image["ImageId"]
         resource_stack = Stack(resource_stack_name, region=region())
         resource_stack.create_stack(template_file=template_path(__file__, TEST_RESOURCES_TEMPLATE), iam_capability=True,
                                     params={
                                         "InstanceAmi": ami,
                                         "InstanceType": "t2.micro",
                                         "TaskListTagName": tasklist_tagname(TESTED_ACTION),
                                         "TaskListTagValue": ",".join(cls.get_methods())
                                     })
         return resource_stack
     except Exception as ex:
         cls.logger.test("Error creating stack {}, {}", resource_stack_name, ex)
         return None
Exemple #12
0
    def test_copy_default_key_encrypted_snapshot_same_region(self):

        test_method = inspect.stack()[0][3]

        self.cleanup_leftover_source_snapshots(test_method)

        self.logger.test("Creating source snapshot")
        source_snapshot_encrypted_default = self.ec2.create_snapshot(
            self.volume_encrypted_default,
            tags={
                "Name": "Ec2CopySnapshot_{}".format(test_method),
                tasklist_tagname(TESTED_ACTION): test_method
            },
            description="Snapshot for testing Ec2CopySnapshot : {}".format(
                test_method))
        self.snapshots.append(source_snapshot_encrypted_default["SnapshotId"])

        parameters = {copy_snapshot.PARAM_DESTINATION_REGION: region()}

        self.logger.test("Running task")
        self.task_runner.run(parameters,
                             task_name=test_method,
                             complete_check_polling_interval=10)
        self.assertTrue(self.task_runner.success(),
                        "Task executed successfully")
        snapshot_copy_id = self.task_runner.results[0].result[
            "copy-snapshot-id"]
        self.snapshots.append(snapshot_copy_id)
        self.logger.test("[X] Task completed")

        self.logger.test("Checking snapshot copy")
        snapshot_copy = self.ec2.get_snapshot(snapshot_copy_id)
        self.assertIsNotNone(snapshot_copy, "Snapshot created")
 def create_resource_stack(cls, resource_stack_name):
     try:
         cls.logger.test("Creating test resources stack {}", resource_stack_name)
         ami = Ec2(region()).latest_aws_linux_image["ImageId"]
         resource_stack = Stack(resource_stack_name, region=region())
         resource_stack.create_stack(template_file=template_path(__file__, TEST_RESOURCES_TEMPLATE),
                                     timeout=1200,
                                     iam_capability=True,
                                     params={
                                         "InstanceAmi": ami,
                                         "InstanceType": TEST_INSTANCE_TYPES[0]
                                     })
         return resource_stack
     except Exception as ex:
         cls.logger.test("Error creating stack {}, {}", resource_stack_name, ex)
         return None
 def create_resource_stack(cls, resource_stack_name):
     try:
         cls.logger.test("Creating test resources stack {}", resource_stack_name)
         resource_stack = Stack(resource_stack_name, region=region())
         resource_stack.create_stack(template_file=template_path(__file__, TEST_RESOURCES_TEMPLATE),
                                     iam_capability=True,
                                     params={})
         return resource_stack
     except Exception as ex:
         cls.logger.test("Error creating stack {}, {}", resource_stack_name, ex)
         return None
Exemple #15
0
 def create_resource_stack(cls, resource_stack_name):
     try:
         cls.logger.test("Creating test resources stack {}", resource_stack_name)
         role = cls.task_runner.action_stack.stack_resources[testing.OPS_AUTOMATOR_ROLE_NAME]["PhysicalResourceId"]
         resource_stack = Stack(resource_stack_name, region=region())
         resource_stack.create_stack(template_file=template_path(__file__, TEST_RESOURCES_TEMPLATE),
                                     iam_capability=True,
                                     params={"TaskRole": role})
         return resource_stack
     except Exception as ex:
         cls.logger.test("Error creating stack {}, {}", resource_stack_name, ex)
         return None
Exemple #16
0
    def setUpClass(cls):

        cls.logger = ConsoleLogger()

        cls.resource_stack = get_resource_stack(
            TESTED_ACTION,
            create_resource_stack_func=cls.create_resource_stack,
            use_existing=KEEP_AND_USE_EXISTING_RESOURCES_STACK,
            region_name=region())
        assert (cls.resource_stack is not None)

        cls.dynamodb = DynamoDB(region=region())

        cls.table_name = cls.resource_stack.stack_outputs["TableName"]
        cls.task_runner = get_task_runner(TESTED_ACTION,
                                          KEEP_AND_USE_EXISTING_ACTION_STACK)

        cls.logger.debug(
            "Waiting for continuous backups to become available for table {}",
            cls.table_name)
        assert (cls.dynamodb.wait_until_table_backups_available(
            cls.table_name))
    def setUpClass(cls):

        cls.logger = ConsoleLogger()

        cls.resource_stack = get_resource_stack(TESTED_ACTION,
                                                create_resource_stack_func=cls.create_resource_stack,
                                                use_existing=KEEP_AND_USE_EXISTING_RESOURCES_STACK, region_name=region())
        assert (cls.resource_stack is not None)
        cls.volume_id = cls.resource_stack.stack_outputs["VolumeId0"]

        cls.ec2 = Ec2(region())

        cls.task_runner = get_task_runner(TESTED_ACTION, KEEP_AND_USE_EXISTING_ACTION_STACK)
 def create_resource_stack(cls, resource_stack_name):
     try:
         cls.logger.test("Creating test resources stack {}", resource_stack_name)
         resource_stack = Stack(resource_stack_name, region=region())
         default_vpc_id = cls.ec2.get_default_vpc()
         assert default_vpc_id is not None
         resource_stack.create_stack(template_file=template_path(__file__, TEST_RESOURCES_TEMPLATE),
                                     timeout=1200,
                                     iam_capability=True,
                                     params={
                                         "VpcId": default_vpc_id["VpcId"],
                                     })
         return resource_stack
     except Exception as ex:
         cls.logger.test("Error creating stack {}, {}", resource_stack_name, ex)
         return None
Exemple #19
0
        def check_snapshot(snap_id, source_volume_id):
            checked_snapshot = self.ec2.get_snapshot(snap_id)
            self.assertIsNotNone(checked_snapshot, "Snapshot does exist")
            self.logger.test("[X] Snapshot was created")

            snapshot_tags = checked_snapshot.get("Tags", {})
            self.assertTrue(TagFilterExpression("InstanceTag=Instance0").is_match(snapshot_tags), "Instance tag copied")
            self.logger.test("[X] Instance tags copied")

            source_volume = self.ec2.get_volume(source_volume_id)
            assert (source_volume is not None)
            device = source_volume.get("Attachments", [{}])[0].get("Device", "")
            if source_volume_id in self.data_volumes:
                volume_tags = source_volume.get("Tags", {})
                self.assertTrue(
                    TagFilterExpression("VolumeTag={}".format(volume_tags.get("VolumeTag", ""))).is_match(snapshot_tags),
                    "Volume tag copied")
            self.logger.test("[X] Volume tags copied")

            snapshot_placeholders = {
                create_snapshot_action.TAG_PLACEHOLDER_VOLUME_ID: source_volume_id,
                create_snapshot_action.TAG_PLACEHOLDER_INSTANCE_ID: self.instance_id,
                create_snapshot_action.TAG_PLACEHOLDER_DEVICE: device
            }
            self.assertTrue(testing.tags.verify_placeholder_tags(snapshot_tags, snapshot_placeholders),
                            "All placeholder tags set on snapshot {}".format(snap_id))
            self.logger.test("[X] Placeholder tags created")

            self.assertTrue(TagFilterExpression(
                "{}={}".format(actions.marker_snapshot_tag_source_source_volume_id(), source_volume_id)).is_match(
                snapshot_tags), "Source volume tag set")
            self.logger.test("[X] Source volume tags created")

            self.assertTrue(self.ec2.get_snapshot_create_volume_permission_users(snap_id) == ["123456789012"],
                            "Create volume permissions set")
            self.logger.test("[X] Volume create permissions set")
            expected_name = "snapshot-{}-{}-{}".format(self.task_runner.action_stack_name, self.instance_id, source_volume_id)
            self.assertEqual(expected_name, snapshot_tags["Name"], "Name has been set")
            self.logger.test("[X] Snapshot name set")

            description = checked_snapshot.get("Description", "")
            self.assertTrue(
                all([p in description for p in [source_volume_id, self.instance_id, region(), self.task_runner.task_name]]),
                "Description is set")
            self.logger.test("[X] Snapshot description set")
Exemple #20
0
 def create_resource_stack(cls, resource_stack_name):
     try:
         cls.logger.test("Creating test resources stack {}",
                         resource_stack_name)
         resource_stack = Stack(resource_stack_name, region=region())
         resource_stack.create_stack(template_file=template_path(
             __file__, TEST_RESOURCES_TEMPLATE),
                                     iam_capability=False,
                                     params={
                                         "IndexName":
                                         INDEX_NAME,
                                         "TaskListTagName":
                                         tasklist_tagname(TESTED_ACTION),
                                         "TaskListTagValue":
                                         "/".join(cls.get_methods())
                                     })
         return resource_stack
     except Exception as ex:
         cls.logger.test("Error creating stack {}, {}", resource_stack_name,
                         ex)
         return None
    def test_delete_by_retention_count(self):

        snapshots_to_create = 4
        snapshots_to_keep = 2

        test_method = inspect.stack()[0][3]

        self.cleanup_leftover_source_snapshots(test_method)

        for i in range(0, snapshots_to_create):
            snapshot = self.ec2.create_snapshot(self.volume_id, tags={
                tasklist_tagname(TESTED_ACTION): test_method
            }, wait_to_complete=300)
            assert (snapshot is not None)
            self.created_snapshots.append(snapshot["SnapshotId"])

        try:
            parameters = {
                delete_snapshot_action.PARAM_RETENTION_COUNT: snapshots_to_keep,
                delete_snapshot_action.PARAM_RETENTION_DAYS: 0
            }

            test_method = inspect.stack()[0][3]

            self.logger.test("Running task")
            self.task_runner.run(parameters,
                                 task_name=test_method, debug=False)
            self.assertTrue(self.task_runner.success(expected_executed_tasks=1), "Task executed successfully")
            self.logger.test("[X] Task completed")

            self.deleted_snapshots = getattr(self.task_runner.results[0], "result", {})["deleted"][region()]

            self.assertEqual(sorted(self.created_snapshots[0:snapshots_to_create - snapshots_to_keep]),
                              sorted(self.deleted_snapshots), "Expected snapshots deleted")
            self.logger.test("[X] {} oldest snapshots deleted out of {}", len(self.deleted_snapshots), len(self.created_snapshots))

            remaining_snapshots = [s["SnapshotId"] for s in self.ec2.get_snapshots_for_volume(volume_id=self.volume_id)]
            self.assertEqual(sorted(self.created_snapshots[snapshots_to_create - snapshots_to_keep:]),
                              sorted(remaining_snapshots), "Expected snapshots retained")
            self.logger.test("[X] {} latest snapshots retained out of {}", len(remaining_snapshots), len(self.created_snapshots))

        finally:
            self.delete_volume_snapshots()
    def test_delete_by_retention_count_with_copied_snapshot(self):

        test_method = inspect.stack()[0][3]

        self.cleanup_leftover_source_snapshots(test_method)

        self.logger.test("Creating (source) snapshot")
        snapshot_source = self.ec2.create_snapshot(self.volume_id, tags={
            tasklist_tagname(TESTED_ACTION): test_method
        }, wait_to_complete=300)
        assert (snapshot_source is not None)
        self.created_snapshots.append(snapshot_source["SnapshotId"])

        self.logger.test("Copying snapshot")
        snapshot_copy = self.ec2.copy_snapshot(snapshot_id=snapshot_source["SnapshotId"], destination_region=region(), tags={
            tasklist_tagname(TESTED_ACTION): test_method
        })
        assert (snapshot_copy is not None)
        self.created_snapshots.append(snapshot_copy["SnapshotId"])
        set_snapshot_sources_tags(snapshot_id=snapshot_copy["SnapshotId"], source_volume_id=self.volume_id,
                                  source_snapshot_id=snapshot_source["SnapshotId"])

        try:
            parameters = {
                delete_snapshot_action.PARAM_RETENTION_COUNT: 1,
                delete_snapshot_action.PARAM_RETENTION_DAYS: 0
            }

            self.logger.test("Running task")
            self.task_runner.run(parameters,
                                 task_name=test_method)
            self.assertTrue(self.task_runner.success(expected_executed_tasks=1), "Task executed successfully")
            self.logger.test("[X] Task completed")

            self.deleted_snapshots = getattr(self.task_runner.results[0], "result", {})["deleted"][region()]

            self.logger.test("Checking deleted snapshot")
            self.assertEqual(1, len(self.deleted_snapshots), "Deleted single snapshot")
            self.assertEqual(self.deleted_snapshots[0], snapshot_source["SnapshotId"], "Oldest (source) snapshot deleted")
            self.logger.test("[X] Source snapshot deleted ")

            remaining_snapshot = self.ec2.get_snapshot(snapshot_copy["SnapshotId"])
            self.assertIsNotNone(remaining_snapshot, "Copied snapshot still exists")
            self.logger.test("[X] Copied snapshot still exists")

        finally:
            self.delete_volume_snapshots()