Repository: cloud-custodian/cloud-custodian

Issue:
aws - glue connection has NoneType error when no VPC
### Describe the bug

When there is no VPC on the Glue connection resource, we get a `TypeError: 'NoneType' object is not iterable` error

### What did you expect to happen?

Succeed in this case.

### Cloud Provider

Amazon Web Services (AWS)

### Cloud Custodian version and dependency information

```shell
Custodian:   0.9.32
Python:      3.9.6 (default, Aug 11 2023, 19:44:49) 
             [Clang 15.0.0 (clang-1500.0.40.1)]
```


### Policy

_No response_

### Relevant log/traceback output

```shell
ERROR    custodian.output:output.py:336 Error while executing policy
Traceback (most recent call last):
  File "/Users/timmygrable/Projects/cloud-custodian/c7n/policy.py", line 330, in run
    resources = self.policy.resource_manager.resources()
  File "/Users/timmygrable/Projects/cloud-custodian/c7n/query.py", line 549, in resources
    resources = self.filter_resources(resources)
  File "/Users/timmygrable/Projects/cloud-custodian/c7n/manager.py", line 112, in filter_resources
    resources = f.process(resources, event)
  File "/Users/timmygrable/Projects/cloud-custodian/c7n/filters/vpc.py", line 98, in process
    related = self.get_related(resources)
  File "/Users/timmygrable/Projects/cloud-custodian/c7n/filters/related.py", line 49, in get_related
    return {r[model.id]: r for r in related
TypeError: 'NoneType' object is not iterable
```


### Extra information or context

_No response_


Discussion:

Resolving patch:
diff --git a/c7n/filters/related.py b/c7n/filters/related.py
--- a/c7n/filters/related.py
+++ b/c7n/filters/related.py
@@ -46,6 +46,10 @@ def get_related(self, resources):
             related = resource_manager.get_resources(list(related_ids))
         else:
             related = resource_manager.resources()
+
+        if related is None:
+            return {}
+
         return {r[model.id]: r for r in related
                 if r[model.id] in related_ids}
 


Test patch:
diff --git a/tests/data/placebo/test_dev_endpoints_query/glue.GetDevEndpoints_1.json b/tests/data/placebo/test_dev_endpoints_query/glue.GetDevEndpoints_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_dev_endpoints_query/glue.GetDevEndpoints_1.json
@@ -0,0 +1,42 @@
+{
+    "status_code": 200,
+    "data": {
+        "DevEndpoints": [
+            {
+                "EndpointName": "endpoint1",
+                "RoleArn": "arn:aws:iam::644160558196:role/c7n-glue-test",
+                "SecurityGroupIds": [],
+                "ZeppelinRemoteSparkInterpreterPort": 0,
+                "Status": "PROVISIONING",
+                "GlueVersion": "1.0",
+                "NumberOfNodes": 3,
+                "AvailabilityZone": "us-east-1b",
+                "CreatedTimestamp": {
+                    "__class__": "datetime",
+                    "year": 2023,
+                    "month": 11,
+                    "day": 20,
+                    "hour": 17,
+                    "minute": 15,
+                    "second": 10,
+                    "microsecond": 982000
+                },
+                "LastModifiedTimestamp": {
+                    "__class__": "datetime",
+                    "year": 2023,
+                    "month": 11,
+                    "day": 20,
+                    "hour": 17,
+                    "minute": 15,
+                    "second": 10,
+                    "microsecond": 982000
+                },
+                "Arguments": {
+                    "GLUE_PYTHON_VERSION": "3"
+                }
+            }
+        ],
+        "NextToken": "",
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_dev_endpoints_query/tagging.GetResources_1.json b/tests/data/placebo/test_dev_endpoints_query/tagging.GetResources_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_dev_endpoints_query/tagging.GetResources_1.json
@@ -0,0 +1,8 @@
+{
+    "status_code": 200,
+    "data": {
+        "PaginationToken": "",
+        "ResourceTagMappingList": [],
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_glue_query_resources/ec2.DescribeSubnets_1.json b/tests/data/placebo/test_glue_query_resources/ec2.DescribeSubnets_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_glue_query_resources/ec2.DescribeSubnets_1.json
@@ -0,0 +1,57 @@
+{
+    "status_code": 200,
+    "data": {
+        "Subnets": [
+            {
+                "AvailabilityZone": "us-east-1a",
+                "AvailabilityZoneId": "use1-az4",
+                "AvailableIpAddressCount": 251,
+                "CidrBlock": "10.0.0.0/24",
+                "DefaultForAz": false,
+                "MapPublicIpOnLaunch": false,
+                "MapCustomerOwnedIpOnLaunch": false,
+                "State": "available",
+                "SubnetId": "subnet-00872ab56d5fa4cdc",
+                "VpcId": "vpc-0503a8b9ddbb3a5c5",
+                "OwnerId": "644160558196",
+                "AssignIpv6AddressOnCreation": false,
+                "Ipv6CidrBlockAssociationSet": [],
+                "Tags": [
+                    {
+                        "Key": "Name",
+                        "Value": "ECS c7n-test-cluster - Public Subnet 1"
+                    },
+                    {
+                        "Key": "aws:cloudformation:stack-id",
+                        "Value": "arn:aws:cloudformation:us-east-1:644160558196:stack/EC2ContainerService-c7n-test-cluster/0c488df0-4827-11ee-8f0c-12a58b5c38f1"
+                    },
+                    {
+                        "Key": "aws:cloudformation:stack-name",
+                        "Value": "EC2ContainerService-c7n-test-cluster"
+                    },
+                    {
+                        "Key": "aws:cloudformation:logical-id",
+                        "Value": "PublicSubnetAz1"
+                    },
+                    {
+                        "Key": "NetworkLocation",
+                        "Value": "Customer"
+                    },
+                    {
+                        "Key": "Description",
+                        "Value": "Created for ECS cluster c7n-test-cluster"
+                    }
+                ],
+                "SubnetArn": "arn:aws:ec2:us-east-1:644160558196:subnet/subnet-00872ab56d5fa4cdc",
+                "EnableDns64": false,
+                "Ipv6Native": false,
+                "PrivateDnsNameOptionsOnLaunch": {
+                    "HostnameType": "ip-name",
+                    "EnableResourceNameDnsARecord": false,
+                    "EnableResourceNameDnsAAAARecord": false
+                }
+            }
+        ],
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_glue_query_resources/glue.GetConnections_1.json b/tests/data/placebo/test_glue_query_resources/glue.GetConnections_1.json
--- a/tests/data/placebo/test_glue_query_resources/glue.GetConnections_1.json
+++ b/tests/data/placebo/test_glue_query_resources/glue.GetConnections_1.json
@@ -1,57 +1,47 @@
 {
-    "status_code": 200, 
+    "status_code": 200,
     "data": {
-        "ResponseMetadata": {
-            "RetryAttempts": 0, 
-            "HTTPStatusCode": 200, 
-            "RequestId": "37c71491-2ea7-11e8-bc67-05ab693096d1", 
-            "HTTPHeaders": {
-                "date": "Fri, 23 Mar 2018 14:33:56 GMT", 
-                "x-amzn-requestid": "37c71491-2ea7-11e8-bc67-05ab693096d1", 
-                "content-length": "467", 
-                "content-type": "application/x-amz-json-1.1", 
-                "connection": "keep-alive"
-            }
-        }, 
         "ConnectionList": [
             {
-                "Name": "c7n-test-connection", 
-                "CreationTime": {
-                    "hour": 10, 
-                    "__class__": "datetime", 
-                    "month": 3, 
-                    "second": 12, 
-                    "microsecond": 358000, 
-                    "year": 2018, 
-                    "day": 23, 
-                    "minute": 30
-                }, 
-                "ConnectionType": "JDBC", 
+                "Name": "test",
+                "Description": "",
+                "ConnectionType": "JDBC",
+                "ConnectionProperties": {
+                    "JDBC_ENFORCE_SSL": "false",
+                    "JDBC_CONNECTION_URL": "jdbc:mysql://database-3-instance-1.cz6wy8cci3uf.us-east-1.rds.amazonaws.com:3306/test",
+                    "SECRET_ID": "c7n",
+                    "KAFKA_SSL_ENABLED": "false"
+                },
                 "PhysicalConnectionRequirements": {
-                    "SubnetId": "subnet-3a334610", 
-                    "AvailabilityZone": "us-east-1d", 
+                    "SubnetId": "subnet-00872ab56d5fa4cdc",
                     "SecurityGroupIdList": [
-                        "sg-6c7fa917"
-                    ]
-                }, 
-                "LastUpdatedBy": "user/joshuaroot", 
+                        "sg-045f7d0c2467c3bfb"
+                    ],
+                    "AvailabilityZone": "us-east-1a"
+                },
+                "CreationTime": {
+                    "__class__": "datetime",
+                    "year": 2020,
+                    "month": 5,
+                    "day": 4,
+                    "hour": 20,
+                    "minute": 1,
+                    "second": 0,
+                    "microsecond": 856000
+                },
                 "LastUpdatedTime": {
-                    "hour": 10, 
-                    "__class__": "datetime", 
-                    "month": 3, 
-                    "second": 12, 
-                    "microsecond": 358000, 
-                    "year": 2018, 
-                    "day": 23, 
-                    "minute": 30
-                }, 
-                "ConnectionProperties": {
-                    "USERNAME": "username", 
-                    "JDBC_CONNECTION_URL": "jdbc:postgresql://localhost:5432/test", 
-                    "PASSWORD": "password"
-                }, 
-                "Description": "Glue test"
+                    "__class__": "datetime",
+                    "year": 2023,
+                    "month": 11,
+                    "day": 20,
+                    "hour": 17,
+                    "minute": 4,
+                    "second": 49,
+                    "microsecond": 864000
+                },
+                "LastUpdatedBy": "user/timmy"
             }
-        ]
+        ],
+        "ResponseMetadata": {}
     }
 }
\ No newline at end of file
diff --git a/tests/data/placebo/test_glue_query_resources/glue.GetDevEndpoints_1.json b/tests/data/placebo/test_glue_query_resources/glue.GetDevEndpoints_1.json
deleted file mode 100644
--- a/tests/data/placebo/test_glue_query_resources/glue.GetDevEndpoints_1.json
+++ /dev/null
@@ -1,50 +0,0 @@
-{
-    "status_code": 200,
-    "data": {
-        "DevEndpoints": [
-            {
-                "EndpointName": "test",
-                "RoleArn": "arn:aws:iam::644160558196:role/c7n-glue-test",
-                "SecurityGroupIds": [],
-                "ZeppelinRemoteSparkInterpreterPort": 9007,
-                "PublicAddress": "ec2-3-94-148-93.compute-1.amazonaws.com",
-                "Status": "READY",
-                "NumberOfNodes": 5,
-                "AvailabilityZone": "us-east-1b",
-                "CreatedTimestamp": {
-                    "__class__": "datetime",
-                    "year": 2019,
-                    "month": 5,
-                    "day": 29,
-                    "hour": 14,
-                    "minute": 45,
-                    "second": 38,
-                    "microsecond": 448000
-                },
-                "LastModifiedTimestamp": {
-                    "__class__": "datetime",
-                    "year": 2019,
-                    "month": 5,
-                    "day": 29,
-                    "hour": 14,
-                    "minute": 54,
-                    "second": 9,
-                    "microsecond": 981000
-                }
-            }
-        ],
-        "NextToken": "",
-        "ResponseMetadata": {
-            "RequestId": "1f7c0173-8247-11e9-97ba-6b7dba7a5ea4",
-            "HTTPStatusCode": 200,
-            "HTTPHeaders": {
-                "date": "Wed, 29 May 2019 19:22:39 GMT",
-                "content-type": "application/x-amz-json-1.1",
-                "content-length": "380",
-                "connection": "keep-alive",
-                "x-amzn-requestid": "1f7c0173-8247-11e9-97ba-6b7dba7a5ea4"
-            },
-            "RetryAttempts": 0
-        }
-    }
-}
\ No newline at end of file
diff --git a/tests/data/placebo/test_glue_query_resources/glue.GetJobs_1.json b/tests/data/placebo/test_glue_query_resources/glue.GetJobs_1.json
deleted file mode 100644
--- a/tests/data/placebo/test_glue_query_resources/glue.GetJobs_1.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{
-    "status_code": 200,
-    "data": {
-        "Jobs": [
-            {
-                "Name": "test",
-                "Role": "arn:aws:iam::644160558196:role/c7n-glue-test",
-                "CreatedOn": {
-                    "__class__": "datetime",
-                    "year": 2019,
-                    "month": 6,
-                    "day": 10,
-                    "hour": 16,
-                    "minute": 19,
-                    "second": 55,
-                    "microsecond": 431000
-                },
-                "LastModifiedOn": {
-                    "__class__": "datetime",
-                    "year": 2019,
-                    "month": 6,
-                    "day": 10,
-                    "hour": 16,
-                    "minute": 19,
-                    "second": 55,
-                    "microsecond": 431000
-                },
-                "ExecutionProperty": {
-                    "MaxConcurrentRuns": 1
-                },
-                "Command": {
-                    "Name": "glueetl",
-                    "ScriptLocation": "s3://aws-glue-scripts-644160558196-us-east-1/david.yun@capitalone.com/test"
-                },
-                "DefaultArguments": {
-                    "--TempDir": "s3://aws-glue-temporary-644160558196-us-east-1/david.yun@capitalone.com",
-                    "--job-bookmark-option": "job-bookmark-disable",
-                    "--job-language": "python"
-                },
-                "Connections": {},
-                "MaxRetries": 0,
-                "AllocatedCapacity": 10,
-                "Timeout": 2880,
-                "MaxCapacity": 10.0
-            }
-        ],
-        "ResponseMetadata": {
-            "RequestId": "1ec2e660-8bbd-11e9-8576-1970c67233c8",
-            "HTTPStatusCode": 200,
-            "HTTPHeaders": {
-                "date": "Mon, 10 Jun 2019 20:19:59 GMT",
-                "content-type": "application/x-amz-json-1.1",
-                "content-length": "594",
-                "connection": "keep-alive",
-                "x-amzn-requestid": "1ec2e660-8bbd-11e9-8576-1970c67233c8"
-            },
-            "RetryAttempts": 0
-        }
-    }
-}
\ No newline at end of file
diff --git a/tests/data/placebo/test_glue_query_resources/tagging.GetResources_1.json b/tests/data/placebo/test_glue_query_resources/tagging.GetResources_1.json
--- a/tests/data/placebo/test_glue_query_resources/tagging.GetResources_1.json
+++ b/tests/data/placebo/test_glue_query_resources/tagging.GetResources_1.json
@@ -4,20 +4,15 @@
         "PaginationToken": "",
         "ResourceTagMappingList": [
             {
-                "ResourceARN": "arn:aws:glue:us-east-1:644160558196:devEndpoint/test",
-                "Tags": []
+                "ResourceARN": "arn:aws:glue:us-east-1:644160558196:connection/test",
+                "Tags": [
+                    {
+                        "Key": "owner",
+                        "Value": "pratyush"
+                    }
+                ]
             }
         ],
-        "ResponseMetadata": {
-            "RequestId": "1fb11b1e-8247-11e9-a0de-99cb9b419859",
-            "HTTPStatusCode": 200,
-            "HTTPHeaders": {
-                "x-amzn-requestid": "1fb11b1e-8247-11e9-a0de-99cb9b419859",
-                "content-type": "application/x-amz-json-1.1",
-                "content-length": "130",
-                "date": "Wed, 29 May 2019 19:22:39 GMT"
-            },
-            "RetryAttempts": 0
-        }
+        "ResponseMetadata": {}
     }
 }
\ No newline at end of file
diff --git a/tests/data/placebo/test_glue_query_resources_no_subnet/ec2.DescribeSubnets_1.json b/tests/data/placebo/test_glue_query_resources_no_subnet/ec2.DescribeSubnets_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_glue_query_resources_no_subnet/ec2.DescribeSubnets_1.json
@@ -0,0 +1,10 @@
+{
+    "status_code": 400,
+    "data": {
+        "Error": {
+            "Code": "InvalidSubnetID.NotFound",
+            "Message": "The subnet ID 'subnet-0cc56341f33e72de0' does not exist"
+        },
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_glue_query_resources_no_subnet/glue.GetConnections_1.json b/tests/data/placebo/test_glue_query_resources_no_subnet/glue.GetConnections_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_glue_query_resources_no_subnet/glue.GetConnections_1.json
@@ -0,0 +1,44 @@
+{
+    "status_code": 200,
+    "data": {
+        "ConnectionList": [
+            {
+                "Name": "test2",
+                "Description": "",
+                "ConnectionType": "NETWORK",
+                "ConnectionProperties": {
+                    "KAFKA_SSL_ENABLED": "false"
+                },
+                "PhysicalConnectionRequirements": {
+                    "SubnetId": "subnet-0cc56341f33e72de0",
+                    "SecurityGroupIdList": [
+                        "sg-09d0fe3ff46b19e83"
+                    ],
+                    "AvailabilityZone": "us-east-1f"
+                },
+                "CreationTime": {
+                    "__class__": "datetime",
+                    "year": 2023,
+                    "month": 11,
+                    "day": 21,
+                    "hour": 15,
+                    "minute": 51,
+                    "second": 14,
+                    "microsecond": 646000
+                },
+                "LastUpdatedTime": {
+                    "__class__": "datetime",
+                    "year": 2023,
+                    "month": 11,
+                    "day": 21,
+                    "hour": 16,
+                    "minute": 22,
+                    "second": 52,
+                    "microsecond": 654000
+                },
+                "LastUpdatedBy": "user/timmy"
+            }
+        ],
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_glue_query_resources_no_subnet/tagging.GetResources_1.json b/tests/data/placebo/test_glue_query_resources_no_subnet/tagging.GetResources_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_glue_query_resources_no_subnet/tagging.GetResources_1.json
@@ -0,0 +1,8 @@
+{
+    "status_code": 200,
+    "data": {
+        "PaginationToken": "",
+        "ResourceTagMappingList": [],
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/test_glue.py b/tests/test_glue.py
--- a/tests/test_glue.py
+++ b/tests/test_glue.py
@@ -102,11 +102,31 @@ def test_glue_connection_tag_untag(self):
         tags = client.get_tags(ResourceArn=arn)
         self.assertEqual(tags.get('Tags'), {})
 
+    def test_glue_query_resources_no_subnet(self):
+        session_factory = self.replay_flight_data("test_glue_query_resources_no_subnet")
+        p = self.load_policy(
+            {
+                "name": "list-glue-connections",
+                "resource": "glue-connection",
+                "filters": [
+                    {
+                        "type": "subnet",
+                        "key": "tag:c7n-internal",
+                        "op": "ne",
+                        "value": "True",
+                    }
+                ],
+            },
+            session_factory=session_factory,
+        )
+        resources = p.run()
+        self.assertEqual(len(resources), 0)
+
 
 class TestGlueDevEndpoints(BaseTest):
 
     def test_dev_endpoints_query(self):
-        session_factory = self.replay_flight_data("test_glue_query_resources")
+        session_factory = self.replay_flight_data("test_dev_endpoints_query")
         p = self.load_policy(
             {"name": "list-glue-dev-endpoints", "resource": "glue-dev-endpoint"},
             session_factory=session_factory,