Repository: cloud-custodian/cloud-custodian

Issue:
rds-snapshot policies in lambda execution mode describe ALL rds snapshots for each resource, causing throttling and timeouts
**Describe the bug**
See https://github.com/cloud-custodian/cloud-custodian/blob/master/c7n/resources/rds.py#L984
The `rds-snapshot` resource has `enum_spec` making a boto call to `describe_db_snapshots` without a resource identifier, so `describe_db_snapshots` retrieves detailed information about _all_ snapshots in the account. When we run this in a lambda, this is triggered once for each snapshot, ultimately making a ton of API calls that causes throttling and execution timeouts.


**Expected behavior**
Provide the unique snapshot identifier in the call to `describe_db_snapshots` so we no longer retrieve info about all snapshots when we're only trying to act upon one of them


Discussion:
kapilt: directconnect, sagemaker-transform-job, key-pair are the remaining ones identified by the meta test.

Patch:
diff --git a/c7n/resources/directconnect.py b/c7n/resources/directconnect.py
index d64989202..99eef4878 100644
--- a/c7n/resources/directconnect.py
+++ b/c7n/resources/directconnect.py
@@ -14,6 +14,7 @@ class DirectConnect(QueryResourceManager):
         id = 'connectionId'
         name = 'connectionName'
         filter_name = 'connectionId'
+        filter_type = 'scalar'
         arn_type = "dxcon"
         universal_taggable = object()
 
diff --git a/c7n/resources/rds.py b/c7n/resources/rds.py
index 93c72d351..3c9a0ca09 100644
--- a/c7n/resources/rds.py
+++ b/c7n/resources/rds.py
@@ -986,6 +986,7 @@ class RDSSnapshot(QueryResourceManager):
         date = 'SnapshotCreateTime'
         config_type = "AWS::RDS::DBSnapshot"
         filter_name = "DBSnapshotIdentifier"
+        filter_type = "scalar"
         universal_taggable = True
         permissions_enum = ('rds:DescribeDBSnapshots',)
 
diff --git a/c7n/resources/sagemaker.py b/c7n/resources/sagemaker.py
index 04f4c51f3..1d4ab5f09 100644
--- a/c7n/resources/sagemaker.py
+++ b/c7n/resources/sagemaker.py
@@ -99,7 +99,8 @@ class SagemakerTransformJob(QueryResourceManager):
         arn = id = 'TransformJobArn'
         name = 'TransformJobName'
         date = 'CreationTime'
-        filter_name = 'TransformJobArn'
+        filter_name = 'NameContains'
+        filter_type = 'scalar'
         permission_augment = ('sagemaker:DescribeTransformJob', 'sagemaker:ListTags')
 
     def __init__(self, ctx, data):
diff --git a/c7n/resources/vpc.py b/c7n/resources/vpc.py
index 5a2f032b4..7d55a4f6f 100644
--- a/c7n/resources/vpc.py
+++ b/c7n/resources/vpc.py
@@ -2300,6 +2300,7 @@ class KeyPair(query.QueryResourceManager):
         id = 'KeyPairId'
         id_prefix = 'key-'
         filter_name = 'KeyNames'
+        filter_type = 'list'
 
 
 @KeyPair.filter_registry.register('unused')


Test patch:
diff --git a/tests/test_policy.py b/tests/test_policy.py
index da9d6b226..6119d4c70 100644
--- a/tests/test_policy.py
+++ b/tests/test_policy.py
@@ -200,6 +200,17 @@ class PolicyMetaLint(BaseTest):
         if names:
             self.fail("%s dont have resource name for reporting" % (", ".join(names)))
 
+    def test_filter_spec(self):
+        missing_fspec = []
+        for k, v in manager.resources.items():
+            if v.resource_type.filter_name is None:
+                continue
+            if not v.resource_type.filter_type:
+                missing_fspec.append(k)
+        if missing_fspec:
+            self.fail('aws resources missing filter specs: %s' % (
+                ', '.join(missing_fspec)))
+
     def test_ec2_id_prefix(self):
         missing_prefix = []
         for k, v in manager.resources.items():