Repository: cloud-custodian/cloud-custodian

Issue:
TypeError: can't compare offset-naive and offset-aware datetimes for snapshot age filter tests
I noticed that the RDS Cluster Snapshot **age** filter test wasn't setup correctly and when I fixed that and ran it I got:

```
$ AWS_ACCESS_KEY_ID=foo AWS_SECRET_ACCESS_KEY=bar AWS_DEFAULT_REGION=us-east-1 ./bin/nosetests tests/test_rdscluster.py
E........
======================================================================
ERROR: test_rdscluster_snapshot_age_filter (tests.test_rdscluster.RDSClusterSnapshotTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/development/cloud-custodian/tests/test_rdscluster.py", line 118, in test_rdscluster_snapshot_age_filter
    resources = p.run()
  File "/development/cloud-custodian/c7n/policy.py", line 299, in __call__
    return self.poll()
  File "/development/cloud-custodian/c7n/policy.py", line 210, in poll
    resources = self.resource_manager.resources()
  File "/development/cloud-custodian/c7n/query.py", line 147, in resources
    return self.filter_resources(resources)
  File "/development/cloud-custodian/c7n/manager.py", line 61, in filter_resources
    resources = f.process(resources, event)
  File "/development/cloud-custodian/c7n/filters/core.py", line 154, in process
    return filter(self, resources)
  File "/development/cloud-custodian/c7n/filters/core.py", line 374, in __call__
    return op(self.threshold_date, v)
TypeError: can't compare offset-naive and offset-aware datetimes
-------------------- >> begin captured logging << --------------------
placebo.pill: DEBUG: attaching to session: Session(region='us-east-1')
placebo.pill: DEBUG: datapath: /development/cloud-custodian/tests/data/placebo/test_rdscluster_snapshot_simple
c7n.cache: DEBUG: Disabling cache
custodian.output: DEBUG: Storing output with <DirectoryOutput to dir:/var/folders/4j/lf5jdq5j4y91g80ytf6qzjwmk6drp5/T/tmplLucNq/rdscluster-snapshot-age-filter>
custodian.policy: INFO: Running policy rdscluster-snapshot-age-filter resource: rds-cluster-snapshot region:us-east-1
placebo.pill: DEBUG: _create_client
placebo.pill: DEBUG: _make_request: rds.DescribeDBClusterSnapshots
placebo.pill: DEBUG: load_response: rds.DescribeDBClusterSnapshots
placebo.pill: DEBUG: get_next_file_path: rds.DescribeDBClusterSnapshots
placebo.pill: DEBUG: load_responses: /development/cloud-custodian/tests/data/placebo/test_rdscluster_snapshot_simple/rds.DescribeDBClusterSnapshots_1.json
custodian.output: ERROR: Error while executing policy
Traceback (most recent call last):
  File "/development/cloud-custodian/c7n/policy.py", line 210, in poll
    resources = self.resource_manager.resources()
  File "/development/cloud-custodian/c7n/query.py", line 147, in resources
    return self.filter_resources(resources)
  File "/development/cloud-custodian/c7n/manager.py", line 61, in filter_resources
    resources = f.process(resources, event)
  File "/development/cloud-custodian/c7n/filters/core.py", line 154, in process
    return filter(self, resources)
  File "/development/cloud-custodian/c7n/filters/core.py", line 374, in __call__
    return op(self.threshold_date, v)
TypeError: can't compare offset-naive and offset-aware datetimes
--------------------- >> end captured logging << ---------------------

----------------------------------------------------------------------
Ran 9 tests in 0.794s

FAILED (errors=1)
```



Discussion:

Resolving patch:
diff --git a/c7n/filters/core.py b/c7n/filters/core.py
--- a/c7n/filters/core.py
+++ b/c7n/filters/core.py
@@ -243,7 +243,7 @@ def validate(self):
         if 'op' in self.data:
             if not self.data['op'] in OPERATORS:
                 raise FilterValidationError(
-                    "Invalid operator in value filter %s" %  self.data)
+                    "Invalid operator in value filter %s" % self.data)
             if self.data['op'] == 'regex':
                 # Sanity check that we can compile
                 try:
@@ -363,6 +363,8 @@ def get_resource_date(self, i):
         v = i[self.date_attribute]
         if not isinstance(v, datetime):
             v = parse(v)
+        if not v.tzinfo:
+            v = v.replace(tzinfo=tzutc())
         return v
 
     def __call__(self, i):


Test patch:
diff --git a/tests/data/placebo/test_rds_snapshot_age_filter/rds.DescribeDBSnapshots_1.json b/tests/data/placebo/test_rds_snapshot_age_filter/rds.DescribeDBSnapshots_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_rds_snapshot_age_filter/rds.DescribeDBSnapshots_1.json
@@ -0,0 +1,49 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {
+            "HTTPStatusCode": 200,
+            "RequestId": "9ec20898-2cce-11e6-9e53-995121fda0e7"
+        },
+        "DBSnapshots": [
+            {
+                "Engine": "postgres",
+                "SnapshotCreateTime": {
+                    "hour": 19,
+                    "__class__": "datetime",
+                    "month": 4,
+                    "second": 52,
+                    "microsecond": 776000,
+                    "year": 2016,
+                    "day": 21,
+                    "minute": 4
+                },
+                "AvailabilityZone": "us-east-1b",
+                "PercentProgress": 100,
+                "MasterUsername": "dbadmin",
+                "Encrypted": true,
+                "LicenseModel": "postgresql-license",
+                "StorageType": "gp2",
+                "Status": "available",
+                "VpcId": "vpc-f3581498",
+                "DBSnapshotIdentifier": "abc-restore-final-snapshot",
+                "InstanceCreateTime": {
+                    "hour": 3,
+                    "__class__": "datetime",
+                    "month": 3,
+                    "second": 42,
+                    "microsecond": 265000,
+                    "year": 2016,
+                    "day": 14,
+                    "minute": 33
+                },
+                "OptionGroupName": "default:postgres-9-4",
+                "AllocatedStorage": 100,
+                "EngineVersion": "9.4.5",
+                "SnapshotType": "manual",
+                "Port": 5432,
+                "DBInstanceIdentifier": "abc-restore"
+            }
+        ]
+    }
+}
diff --git a/tests/test_rds.py b/tests/test_rds.py
--- a/tests/test_rds.py
+++ b/tests/test_rds.py
@@ -271,7 +271,17 @@ def test_rds_db_instance_eligible_for_backup(self):
         self.assertTrue(rds._db_instance_eligible_for_backup(resource))
 
 
-class RDSSnapshotTrimTest(BaseTest):
+class RDSSnapshotTest(BaseTest):
+
+    def test_rds_snapshot_age_filter(self):
+        factory = self.replay_flight_data('test_rds_snapshot_age_filter')
+        p = self.load_policy({
+            'name': 'rds-snapshot-age-filter',
+            'resource': 'rds-snapshot',
+            'filters': [{'type': 'age', 'days': 7}]},
+            session_factory=factory)
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
 
     def test_rds_snapshot_trim(self):
         factory = self.replay_flight_data('test_rds_snapshot_delete')
diff --git a/tests/test_rdscluster.py b/tests/test_rdscluster.py
--- a/tests/test_rdscluster.py
+++ b/tests/test_rdscluster.py
@@ -95,7 +95,7 @@ def test_rdscluster_snapshot_simple(self):
         resources = p.run()
         self.assertEqual(len(resources), 2)
 
-    def test_rdscluster_simple_filter(self):
+    def test_rdscluster_snapshot_simple_filter(self):
         session_factory = self.replay_flight_data('test_rdscluster_snapshot_simple')
         p = self.load_policy({
             'name': 'rdscluster-snapshot-simple-filter',
@@ -108,12 +108,12 @@ def test_rdscluster_simple_filter(self):
         resources = p.run()
         self.assertEqual(len(resources), 1)
 
-    def test_rdscluster_snapshot_trim(self):
+    def test_rdscluster_snapshot_age_filter(self):
         factory = self.replay_flight_data('test_rdscluster_snapshot_simple')
         p = self.load_policy({
             'name': 'rdscluster-snapshot-age-filter',
             'resource': 'rds-cluster-snapshot',
-            'filters': [{'age': 7}]},
+            'filters': [{'type': 'age', 'days': 7}]},
             session_factory=factory)
         resources = p.run()
         self.assertEqual(len(resources), 2)