Repository: cloud-custodian/cloud-custodian

Issue:
Add support for backup in timestream backup
### Describe the feature

This will use AWS backup service to take time-stream backup.

### Extra information or context

_No response_


Discussion:
i will be working on this one

Resolving patch:
diff --git a/c7n/resources/timestream.py b/c7n/resources/timestream.py
--- a/c7n/resources/timestream.py
+++ b/c7n/resources/timestream.py
@@ -9,6 +9,7 @@
     Tag as TagAction,
     RemoveTag as RemoveTagAction
 )
+from c7n.filters.backup import ConsecutiveAwsBackupsFilter
 
 
 class DescribeTimestream(DescribeSource):
@@ -138,6 +139,9 @@ def process(self, resources):
                 )
 
 
+TimestreamTable.filter_registry.register('consecutive-aws-backups', ConsecutiveAwsBackupsFilter)
+
+
 @TimestreamDatabase.filter_registry.register('kms-key')
 class KmsFilter(KmsRelatedFilter):
     RelatedIdsExpression = 'KmsKeyId'


Test patch:
diff --git a/tests/data/placebo/test_timestream_consecutive_backup_count_filter/backup.ListRecoveryPointsByResource_1.json b/tests/data/placebo/test_timestream_consecutive_backup_count_filter/backup.ListRecoveryPointsByResource_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_timestream_consecutive_backup_count_filter/backup.ListRecoveryPointsByResource_1.json
@@ -0,0 +1,28 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "RecoveryPoints": [
+            {
+                "RecoveryPointArn": "arn:aws:backup:us-east-1:644160558196:recovery-point:757807c0-ef88-4055-aa6f-b7f2ac04e8b5",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2024,
+                    "month": 5,
+                    "day": 13,
+                    "hour": 22,
+                    "minute": 10,
+                    "second": 12,
+                    "microsecond": 899000
+                },
+                "Status": "COMPLETED",
+                "EncryptionKeyArn": "arn:aws:kms:us-east-1:644160558196:key/5d97ffc0-5842-49ce-9daf-6d0a129bf6c8",
+                "BackupSizeBytes": 0,
+                "BackupVaultName": "Default",
+                "IsParent": false,
+                "ResourceName": "database/test-timestream/table/test-2",
+                "VaultType": "BACKUP_VAULT"
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_timestream_consecutive_backup_count_filter/ingest.timestream.DescribeEndpoints_1.json b/tests/data/placebo/test_timestream_consecutive_backup_count_filter/ingest.timestream.DescribeEndpoints_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_timestream_consecutive_backup_count_filter/ingest.timestream.DescribeEndpoints_1.json
@@ -0,0 +1,12 @@
+{
+    "status_code": 200,
+    "data": {
+        "Endpoints": [
+            {
+                "Address": "ingest-cell2.timestream.us-east-1.amazonaws.com",
+                "CachePeriodInMinutes": 1440
+            }
+        ],
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_timestream_consecutive_backup_count_filter/ingest.timestream.DescribeEndpoints_2.json b/tests/data/placebo/test_timestream_consecutive_backup_count_filter/ingest.timestream.DescribeEndpoints_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_timestream_consecutive_backup_count_filter/ingest.timestream.DescribeEndpoints_2.json
@@ -0,0 +1,12 @@
+{
+    "status_code": 200,
+    "data": {
+        "Endpoints": [
+            {
+                "Address": "ingest-cell2.timestream.us-east-1.amazonaws.com",
+                "CachePeriodInMinutes": 1440
+            }
+        ],
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_timestream_consecutive_backup_count_filter/ingest.timestream.ListTables_1.json b/tests/data/placebo/test_timestream_consecutive_backup_count_filter/ingest.timestream.ListTables_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_timestream_consecutive_backup_count_filter/ingest.timestream.ListTables_1.json
@@ -0,0 +1,48 @@
+{
+    "status_code": 200,
+    "data": {
+        "Tables": [
+            {
+                "Arn": "arn:aws:timestream:us-east-1:644160558196:database/test-timestream/table/test-2",
+                "TableName": "test-2",
+                "DatabaseName": "test-timestream",
+                "TableStatus": "ACTIVE",
+                "RetentionProperties": {
+                    "MemoryStoreRetentionPeriodInHours": 12,
+                    "MagneticStoreRetentionPeriodInDays": 1
+                },
+                "CreationTime": {
+                    "__class__": "datetime",
+                    "year": 2024,
+                    "month": 5,
+                    "day": 13,
+                    "hour": 22,
+                    "minute": 2,
+                    "second": 21,
+                    "microsecond": 252000
+                },
+                "LastUpdatedTime": {
+                    "__class__": "datetime",
+                    "year": 2024,
+                    "month": 5,
+                    "day": 13,
+                    "hour": 22,
+                    "minute": 2,
+                    "second": 21,
+                    "microsecond": 244000
+                },
+                "MagneticStoreWriteProperties": {
+                    "EnableMagneticStoreWrites": false
+                },
+                "Schema": {
+                    "CompositePartitionKey": [
+                        {
+                            "Type": "MEASURE"
+                        }
+                    ]
+                }
+            }
+        ],
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_timestream_consecutive_backup_count_filter/ingest.timestream.ListTagsForResource_1.json b/tests/data/placebo/test_timestream_consecutive_backup_count_filter/ingest.timestream.ListTagsForResource_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_timestream_consecutive_backup_count_filter/ingest.timestream.ListTagsForResource_1.json
@@ -0,0 +1,7 @@
+{
+    "status_code": 200,
+    "data": {
+        "Tags": [],
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/test_timestream.py b/tests/test_timestream.py
--- a/tests/test_timestream.py
+++ b/tests/test_timestream.py
@@ -1,6 +1,9 @@
 # Copyright The Cloud Custodian Authors.
 # SPDX-License-Identifier: Apache-2.0
 from .common import BaseTest
+from c7n.testing import mock_datetime_now
+import c7n.filters.backup
+from dateutil import parser
 
 
 class TestTimestreamDatabase(BaseTest):
@@ -171,6 +174,28 @@ def test_timestream_table_delete(self):
         tables = client.list_tables()['Tables']
         self.assertEqual(len(tables), 0)
 
+    def test_timestream_consecutive_aws_backup_count_filter(self):
+        session_factory = self.replay_flight_data("test_timestream_consecutive_backup_count_filter")
+        p = self.load_policy(
+            {
+                "name": "timestream_consecutive_aws_backup_count_filter",
+                "resource": "aws.timestream-table",
+                "filters": [
+                    {
+                        "type": "consecutive-aws-backups",
+                        "count": 1,
+                        "period": "days",
+                        "status": "COMPLETED"
+                    }
+                ]
+            },
+            session_factory=session_factory,
+        )
+        with mock_datetime_now(parser.parse("2024-05-14T22:00:00+00:00"), c7n.filters.backup):
+            resources = p.run()
+        self.assertEqual(resources[0]['c7n:AwsBackups'][0]['Status'], "COMPLETED")
+        self.assertEqual(len(resources), 1)
+
     def test_timestream_kms_key_filter(self):
         session_factory = self.replay_flight_data('test_timestream_kms_key_filter')
         p = self.load_policy(