aws-inventory-manager 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of aws-inventory-manager might be problematic. Click here for more details.

Files changed (65) hide show
  1. aws_inventory_manager-0.2.0.dist-info/METADATA +508 -0
  2. aws_inventory_manager-0.2.0.dist-info/RECORD +65 -0
  3. aws_inventory_manager-0.2.0.dist-info/WHEEL +5 -0
  4. aws_inventory_manager-0.2.0.dist-info/entry_points.txt +2 -0
  5. aws_inventory_manager-0.2.0.dist-info/licenses/LICENSE +21 -0
  6. aws_inventory_manager-0.2.0.dist-info/top_level.txt +1 -0
  7. src/__init__.py +3 -0
  8. src/aws/__init__.py +11 -0
  9. src/aws/client.py +128 -0
  10. src/aws/credentials.py +191 -0
  11. src/aws/rate_limiter.py +177 -0
  12. src/cli/__init__.py +5 -0
  13. src/cli/config.py +130 -0
  14. src/cli/main.py +1450 -0
  15. src/cost/__init__.py +5 -0
  16. src/cost/analyzer.py +226 -0
  17. src/cost/explorer.py +209 -0
  18. src/cost/reporter.py +237 -0
  19. src/delta/__init__.py +5 -0
  20. src/delta/calculator.py +180 -0
  21. src/delta/reporter.py +225 -0
  22. src/models/__init__.py +17 -0
  23. src/models/cost_report.py +87 -0
  24. src/models/delta_report.py +111 -0
  25. src/models/inventory.py +124 -0
  26. src/models/resource.py +99 -0
  27. src/models/snapshot.py +108 -0
  28. src/snapshot/__init__.py +6 -0
  29. src/snapshot/capturer.py +347 -0
  30. src/snapshot/filter.py +245 -0
  31. src/snapshot/inventory_storage.py +264 -0
  32. src/snapshot/resource_collectors/__init__.py +5 -0
  33. src/snapshot/resource_collectors/apigateway.py +140 -0
  34. src/snapshot/resource_collectors/backup.py +136 -0
  35. src/snapshot/resource_collectors/base.py +81 -0
  36. src/snapshot/resource_collectors/cloudformation.py +55 -0
  37. src/snapshot/resource_collectors/cloudwatch.py +109 -0
  38. src/snapshot/resource_collectors/codebuild.py +69 -0
  39. src/snapshot/resource_collectors/codepipeline.py +82 -0
  40. src/snapshot/resource_collectors/dynamodb.py +65 -0
  41. src/snapshot/resource_collectors/ec2.py +240 -0
  42. src/snapshot/resource_collectors/ecs.py +215 -0
  43. src/snapshot/resource_collectors/eks.py +200 -0
  44. src/snapshot/resource_collectors/elb.py +126 -0
  45. src/snapshot/resource_collectors/eventbridge.py +156 -0
  46. src/snapshot/resource_collectors/iam.py +188 -0
  47. src/snapshot/resource_collectors/kms.py +111 -0
  48. src/snapshot/resource_collectors/lambda_func.py +112 -0
  49. src/snapshot/resource_collectors/rds.py +109 -0
  50. src/snapshot/resource_collectors/route53.py +86 -0
  51. src/snapshot/resource_collectors/s3.py +105 -0
  52. src/snapshot/resource_collectors/secretsmanager.py +70 -0
  53. src/snapshot/resource_collectors/sns.py +68 -0
  54. src/snapshot/resource_collectors/sqs.py +72 -0
  55. src/snapshot/resource_collectors/ssm.py +160 -0
  56. src/snapshot/resource_collectors/stepfunctions.py +74 -0
  57. src/snapshot/resource_collectors/vpcendpoints.py +79 -0
  58. src/snapshot/resource_collectors/waf.py +159 -0
  59. src/snapshot/storage.py +259 -0
  60. src/utils/__init__.py +12 -0
  61. src/utils/export.py +87 -0
  62. src/utils/hash.py +60 -0
  63. src/utils/logging.py +63 -0
  64. src/utils/paths.py +51 -0
  65. src/utils/progress.py +41 -0
@@ -0,0 +1,240 @@
1
+ """EC2 resource collector."""
2
+
3
+ from typing import List
4
+
5
+ from ...models.resource import Resource
6
+ from ...utils.hash import compute_config_hash
7
+ from .base import BaseResourceCollector
8
+
9
+
10
+ class EC2Collector(BaseResourceCollector):
11
+ """Collector for AWS EC2 resources (instances, volumes, VPCs, security groups, etc.)."""
12
+
13
+ @property
14
+ def service_name(self) -> str:
15
+ return "ec2"
16
+
17
+ def collect(self) -> List[Resource]:
18
+ """Collect EC2 resources.
19
+
20
+ Returns:
21
+ List of EC2 resources
22
+ """
23
+ resources = []
24
+ account_id = self._get_account_id()
25
+
26
+ # Collect instances
27
+ resources.extend(self._collect_instances(account_id))
28
+
29
+ # Collect volumes
30
+ resources.extend(self._collect_volumes(account_id))
31
+
32
+ # Collect VPCs
33
+ resources.extend(self._collect_vpcs(account_id))
34
+
35
+ # Collect security groups
36
+ resources.extend(self._collect_security_groups(account_id))
37
+
38
+ # Collect subnets
39
+ resources.extend(self._collect_subnets(account_id))
40
+
41
+ self.logger.debug(f"Collected {len(resources)} EC2 resources in {self.region}")
42
+ return resources
43
+
44
+ def _collect_instances(self, account_id: str) -> List[Resource]:
45
+ """Collect EC2 instances."""
46
+ resources = []
47
+ client = self._create_client()
48
+
49
+ try:
50
+ paginator = client.get_paginator("describe_instances")
51
+ for page in paginator.paginate():
52
+ for reservation in page["Reservations"]:
53
+ for instance in reservation["Instances"]:
54
+ instance_id = instance["InstanceId"]
55
+
56
+ # Extract tags
57
+ tags = {}
58
+ for tag in instance.get("Tags", []):
59
+ tags[tag["Key"]] = tag["Value"]
60
+
61
+ # Get instance name from tags
62
+ name = tags.get("Name", instance_id)
63
+
64
+ # Build ARN
65
+ arn = f"arn:aws:ec2:{self.region}:{account_id}:instance/{instance_id}"
66
+
67
+ # Create resource
68
+ resource = Resource(
69
+ arn=arn,
70
+ resource_type="AWS::EC2::Instance",
71
+ name=name,
72
+ region=self.region,
73
+ tags=tags,
74
+ config_hash=compute_config_hash(instance),
75
+ created_at=instance.get("LaunchTime"),
76
+ raw_config=instance,
77
+ )
78
+ resources.append(resource)
79
+
80
+ except Exception as e:
81
+ self.logger.error(f"Error collecting EC2 instances in {self.region}: {e}")
82
+
83
+ return resources
84
+
85
+ def _collect_volumes(self, account_id: str) -> List[Resource]:
86
+ """Collect EBS volumes."""
87
+ resources = []
88
+ client = self._create_client()
89
+
90
+ try:
91
+ paginator = client.get_paginator("describe_volumes")
92
+ for page in paginator.paginate():
93
+ for volume in page["Volumes"]:
94
+ volume_id = volume["VolumeId"]
95
+
96
+ # Extract tags
97
+ tags = {}
98
+ for tag in volume.get("Tags", []):
99
+ tags[tag["Key"]] = tag["Value"]
100
+
101
+ # Get volume name from tags
102
+ name = tags.get("Name", volume_id)
103
+
104
+ # Build ARN
105
+ arn = f"arn:aws:ec2:{self.region}:{account_id}:volume/{volume_id}"
106
+
107
+ # Create resource
108
+ resource = Resource(
109
+ arn=arn,
110
+ resource_type="AWS::EC2::Volume",
111
+ name=name,
112
+ region=self.region,
113
+ tags=tags,
114
+ config_hash=compute_config_hash(volume),
115
+ created_at=volume.get("CreateTime"),
116
+ raw_config=volume,
117
+ )
118
+ resources.append(resource)
119
+
120
+ except Exception as e:
121
+ self.logger.error(f"Error collecting EBS volumes in {self.region}: {e}")
122
+
123
+ return resources
124
+
125
+ def _collect_vpcs(self, account_id: str) -> List[Resource]:
126
+ """Collect VPCs."""
127
+ resources = []
128
+ client = self._create_client()
129
+
130
+ try:
131
+ response = client.describe_vpcs()
132
+ for vpc in response["Vpcs"]:
133
+ vpc_id = vpc["VpcId"]
134
+
135
+ # Extract tags
136
+ tags = {}
137
+ for tag in vpc.get("Tags", []):
138
+ tags[tag["Key"]] = tag["Value"]
139
+
140
+ # Get VPC name from tags
141
+ name = tags.get("Name", vpc_id)
142
+
143
+ # Build ARN
144
+ arn = f"arn:aws:ec2:{self.region}:{account_id}:vpc/{vpc_id}"
145
+
146
+ # Create resource
147
+ resource = Resource(
148
+ arn=arn,
149
+ resource_type="AWS::EC2::VPC",
150
+ name=name,
151
+ region=self.region,
152
+ tags=tags,
153
+ config_hash=compute_config_hash(vpc),
154
+ created_at=None, # VPCs don't have creation timestamp
155
+ raw_config=vpc,
156
+ )
157
+ resources.append(resource)
158
+
159
+ except Exception as e:
160
+ self.logger.error(f"Error collecting VPCs in {self.region}: {e}")
161
+
162
+ return resources
163
+
164
+ def _collect_security_groups(self, account_id: str) -> List[Resource]:
165
+ """Collect security groups."""
166
+ resources = []
167
+ client = self._create_client()
168
+
169
+ try:
170
+ paginator = client.get_paginator("describe_security_groups")
171
+ for page in paginator.paginate():
172
+ for sg in page["SecurityGroups"]:
173
+ sg_id = sg["GroupId"]
174
+ sg_name = sg["GroupName"]
175
+
176
+ # Extract tags
177
+ tags = {}
178
+ for tag in sg.get("Tags", []):
179
+ tags[tag["Key"]] = tag["Value"]
180
+
181
+ # Build ARN
182
+ arn = f"arn:aws:ec2:{self.region}:{account_id}:security-group/{sg_id}"
183
+
184
+ # Create resource
185
+ resource = Resource(
186
+ arn=arn,
187
+ resource_type="AWS::EC2::SecurityGroup",
188
+ name=sg_name,
189
+ region=self.region,
190
+ tags=tags,
191
+ config_hash=compute_config_hash(sg),
192
+ created_at=None, # Security groups don't have creation timestamp
193
+ raw_config=sg,
194
+ )
195
+ resources.append(resource)
196
+
197
+ except Exception as e:
198
+ self.logger.error(f"Error collecting security groups in {self.region}: {e}")
199
+
200
+ return resources
201
+
202
+ def _collect_subnets(self, account_id: str) -> List[Resource]:
203
+ """Collect subnets."""
204
+ resources = []
205
+ client = self._create_client()
206
+
207
+ try:
208
+ paginator = client.get_paginator("describe_subnets")
209
+ for page in paginator.paginate():
210
+ for subnet in page["Subnets"]:
211
+ subnet_id = subnet["SubnetId"]
212
+
213
+ # Extract tags
214
+ tags = {}
215
+ for tag in subnet.get("Tags", []):
216
+ tags[tag["Key"]] = tag["Value"]
217
+
218
+ # Get subnet name from tags
219
+ name = tags.get("Name", subnet_id)
220
+
221
+ # Build ARN
222
+ arn = f"arn:aws:ec2:{self.region}:{account_id}:subnet/{subnet_id}"
223
+
224
+ # Create resource
225
+ resource = Resource(
226
+ arn=arn,
227
+ resource_type="AWS::EC2::Subnet",
228
+ name=name,
229
+ region=self.region,
230
+ tags=tags,
231
+ config_hash=compute_config_hash(subnet),
232
+ created_at=None, # Subnets don't have creation timestamp
233
+ raw_config=subnet,
234
+ )
235
+ resources.append(resource)
236
+
237
+ except Exception as e:
238
+ self.logger.error(f"Error collecting subnets in {self.region}: {e}")
239
+
240
+ return resources
@@ -0,0 +1,215 @@
1
+ """ECS resource collector."""
2
+
3
+ from typing import List
4
+
5
+ from ...models.resource import Resource
6
+ from ...utils.hash import compute_config_hash
7
+ from .base import BaseResourceCollector
8
+
9
+
10
+ class ECSCollector(BaseResourceCollector):
11
+ """Collector for Amazon ECS (Elastic Container Service) resources."""
12
+
13
+ @property
14
+ def service_name(self) -> str:
15
+ return "ecs"
16
+
17
+ def collect(self) -> List[Resource]:
18
+ """Collect ECS resources.
19
+
20
+ Collects:
21
+ - ECS Clusters
22
+ - ECS Services (within each cluster)
23
+ - ECS Task Definitions (active revisions)
24
+
25
+ Returns:
26
+ List of ECS resources
27
+ """
28
+ resources = []
29
+
30
+ # Collect clusters
31
+ resources.extend(self._collect_clusters())
32
+
33
+ # Collect services (across all clusters)
34
+ resources.extend(self._collect_services())
35
+
36
+ # Collect task definitions
37
+ resources.extend(self._collect_task_definitions())
38
+
39
+ self.logger.debug(f"Collected {len(resources)} ECS resources in {self.region}")
40
+ return resources
41
+
42
+ def _collect_clusters(self) -> List[Resource]:
43
+ """Collect ECS clusters.
44
+
45
+ Returns:
46
+ List of ECS cluster resources
47
+ """
48
+ resources = []
49
+ client = self._create_client()
50
+
51
+ try:
52
+ paginator = client.get_paginator("list_clusters")
53
+ for page in paginator.paginate():
54
+ cluster_arns = page.get("clusterArns", [])
55
+
56
+ if not cluster_arns:
57
+ continue
58
+
59
+ # Get detailed info for clusters (in batches of 100)
60
+ for i in range(0, len(cluster_arns), 100):
61
+ batch = cluster_arns[i : i + 100]
62
+ try:
63
+ response = client.describe_clusters(clusters=batch, include=["TAGS"])
64
+ for cluster in response.get("clusters", []):
65
+ cluster_name = cluster["clusterName"]
66
+ cluster_arn = cluster["clusterArn"]
67
+
68
+ # Extract tags
69
+ tags = {}
70
+ for tag in cluster.get("tags", []):
71
+ tags[tag["key"]] = tag["value"]
72
+
73
+ # Extract creation timestamp (not always available)
74
+ created_at = None
75
+
76
+ # Create resource
77
+ resource = Resource(
78
+ arn=cluster_arn,
79
+ resource_type="AWS::ECS::Cluster",
80
+ name=cluster_name,
81
+ region=self.region,
82
+ tags=tags,
83
+ config_hash=compute_config_hash(cluster),
84
+ created_at=created_at,
85
+ raw_config=cluster,
86
+ )
87
+ resources.append(resource)
88
+
89
+ except Exception as e:
90
+ self.logger.debug(f"Error describing cluster batch: {e}")
91
+
92
+ except Exception as e:
93
+ self.logger.error(f"Error collecting ECS clusters in {self.region}: {e}")
94
+
95
+ return resources
96
+
97
+ def _collect_services(self) -> List[Resource]:
98
+ """Collect ECS services across all clusters.
99
+
100
+ Returns:
101
+ List of ECS service resources
102
+ """
103
+ resources = []
104
+ client = self._create_client()
105
+
106
+ try:
107
+ # First, get all clusters
108
+ cluster_arns = []
109
+ paginator = client.get_paginator("list_clusters")
110
+ for page in paginator.paginate():
111
+ cluster_arns.extend(page.get("clusterArns", []))
112
+
113
+ # Collect services from each cluster
114
+ for cluster_arn in cluster_arns:
115
+ try:
116
+ service_paginator = client.get_paginator("list_services")
117
+ service_arns = []
118
+ for page in service_paginator.paginate(cluster=cluster_arn):
119
+ service_arns.extend(page.get("serviceArns", []))
120
+
121
+ if not service_arns:
122
+ continue
123
+
124
+ # Get detailed info for services (in batches of 10)
125
+ for i in range(0, len(service_arns), 10):
126
+ batch = service_arns[i : i + 10]
127
+ try:
128
+ response = client.describe_services(cluster=cluster_arn, services=batch, include=["TAGS"])
129
+ for service in response.get("services", []):
130
+ service_name = service["serviceName"]
131
+ service_arn = service["serviceArn"]
132
+
133
+ # Extract tags
134
+ tags = {}
135
+ for tag in service.get("tags", []):
136
+ tags[tag["key"]] = tag["value"]
137
+
138
+ # Extract creation date
139
+ created_at = service.get("createdAt")
140
+
141
+ # Create resource
142
+ resource = Resource(
143
+ arn=service_arn,
144
+ resource_type="AWS::ECS::Service",
145
+ name=service_name,
146
+ region=self.region,
147
+ tags=tags,
148
+ config_hash=compute_config_hash(service),
149
+ created_at=created_at,
150
+ raw_config=service,
151
+ )
152
+ resources.append(resource)
153
+
154
+ except Exception as e:
155
+ self.logger.debug(f"Error describing service batch: {e}")
156
+
157
+ except Exception as e:
158
+ self.logger.debug(f"Error collecting services from cluster {cluster_arn}: {e}")
159
+
160
+ except Exception as e:
161
+ self.logger.error(f"Error collecting ECS services in {self.region}: {e}")
162
+
163
+ return resources
164
+
165
+ def _collect_task_definitions(self) -> List[Resource]:
166
+ """Collect ECS task definitions (active revisions only).
167
+
168
+ Returns:
169
+ List of ECS task definition resources
170
+ """
171
+ resources = []
172
+ client = self._create_client()
173
+
174
+ try:
175
+ paginator = client.get_paginator("list_task_definitions")
176
+ for page in paginator.paginate(status="ACTIVE"):
177
+ for task_def_arn in page.get("taskDefinitionArns", []):
178
+ try:
179
+ # Get task definition details
180
+ response = client.describe_task_definition(taskDefinition=task_def_arn, include=["TAGS"])
181
+ task_def = response.get("taskDefinition", {})
182
+
183
+ # Extract family and revision
184
+ family = task_def.get("family", "unknown")
185
+ revision = task_def.get("revision", 0)
186
+ name = f"{family}:{revision}"
187
+
188
+ # Extract tags
189
+ tags = {}
190
+ for tag in response.get("tags", []):
191
+ tags[tag["key"]] = tag["value"]
192
+
193
+ # Task definitions don't have creation timestamp
194
+ created_at = None
195
+
196
+ # Create resource
197
+ resource = Resource(
198
+ arn=task_def_arn,
199
+ resource_type="AWS::ECS::TaskDefinition",
200
+ name=name,
201
+ region=self.region,
202
+ tags=tags,
203
+ config_hash=compute_config_hash(task_def),
204
+ created_at=created_at,
205
+ raw_config=task_def,
206
+ )
207
+ resources.append(resource)
208
+
209
+ except Exception as e:
210
+ self.logger.debug(f"Error describing task definition {task_def_arn}: {e}")
211
+
212
+ except Exception as e:
213
+ self.logger.error(f"Error collecting ECS task definitions in {self.region}: {e}")
214
+
215
+ return resources
@@ -0,0 +1,200 @@
1
+ """EKS resource collector."""
2
+
3
+ from typing import List
4
+
5
+ from ...models.resource import Resource
6
+ from ...utils.hash import compute_config_hash
7
+ from .base import BaseResourceCollector
8
+
9
+
10
+ class EKSCollector(BaseResourceCollector):
11
+ """Collector for Amazon EKS (Elastic Kubernetes Service) resources."""
12
+
13
+ @property
14
+ def service_name(self) -> str:
15
+ return "eks"
16
+
17
+ def collect(self) -> List[Resource]:
18
+ """Collect EKS resources.
19
+
20
+ Collects:
21
+ - EKS Clusters
22
+ - Node Groups (within each cluster)
23
+ - Fargate Profiles (within each cluster)
24
+
25
+ Returns:
26
+ List of EKS resources
27
+ """
28
+ resources = []
29
+
30
+ # Collect clusters
31
+ cluster_resources, cluster_names = self._collect_clusters()
32
+ resources.extend(cluster_resources)
33
+
34
+ # Collect node groups for each cluster
35
+ resources.extend(self._collect_node_groups(cluster_names))
36
+
37
+ # Collect Fargate profiles for each cluster
38
+ resources.extend(self._collect_fargate_profiles(cluster_names))
39
+
40
+ self.logger.debug(f"Collected {len(resources)} EKS resources in {self.region}")
41
+ return resources
42
+
43
+ def _collect_clusters(self) -> tuple[List[Resource], List[str]]: # type: ignore
44
+ """Collect EKS clusters.
45
+
46
+ Returns:
47
+ Tuple of (list of cluster resources, list of cluster names)
48
+ """
49
+ resources = []
50
+ cluster_names = []
51
+ client = self._create_client()
52
+
53
+ try:
54
+ paginator = client.get_paginator("list_clusters")
55
+ for page in paginator.paginate():
56
+ for cluster_name in page.get("clusters", []):
57
+ cluster_names.append(cluster_name)
58
+
59
+ try:
60
+ # Get detailed cluster info
61
+ cluster_response = client.describe_cluster(name=cluster_name)
62
+ cluster = cluster_response.get("cluster", {})
63
+
64
+ cluster_arn = cluster.get("arn", "")
65
+
66
+ # Extract tags
67
+ tags = cluster.get("tags", {})
68
+
69
+ # Extract creation date
70
+ created_at = cluster.get("createdAt")
71
+
72
+ # Create resource
73
+ resource = Resource(
74
+ arn=cluster_arn,
75
+ resource_type="AWS::EKS::Cluster",
76
+ name=cluster_name,
77
+ region=self.region,
78
+ tags=tags,
79
+ config_hash=compute_config_hash(cluster),
80
+ created_at=created_at,
81
+ raw_config=cluster,
82
+ )
83
+ resources.append(resource)
84
+
85
+ except Exception as e:
86
+ self.logger.debug(f"Error processing cluster {cluster_name}: {e}")
87
+ continue
88
+
89
+ except Exception as e:
90
+ self.logger.error(f"Error collecting EKS clusters in {self.region}: {e}")
91
+
92
+ return resources, cluster_names
93
+
94
+ def _collect_node_groups(self, cluster_names: List[str]) -> List[Resource]:
95
+ """Collect EKS node groups for given clusters.
96
+
97
+ Args:
98
+ cluster_names: List of cluster names to collect node groups from
99
+
100
+ Returns:
101
+ List of node group resources
102
+ """
103
+ resources = []
104
+ client = self._create_client()
105
+
106
+ for cluster_name in cluster_names:
107
+ try:
108
+ paginator = client.get_paginator("list_nodegroups")
109
+ for page in paginator.paginate(clusterName=cluster_name):
110
+ for nodegroup_name in page.get("nodegroups", []):
111
+ try:
112
+ # Get detailed node group info
113
+ ng_response = client.describe_nodegroup(
114
+ clusterName=cluster_name, nodegroupName=nodegroup_name
115
+ )
116
+ nodegroup = ng_response.get("nodegroup", {})
117
+
118
+ ng_arn = nodegroup.get("nodegroupArn", "")
119
+
120
+ # Extract tags
121
+ tags = nodegroup.get("tags", {})
122
+
123
+ # Extract creation date
124
+ created_at = nodegroup.get("createdAt")
125
+
126
+ # Create resource
127
+ resource = Resource(
128
+ arn=ng_arn,
129
+ resource_type="AWS::EKS::Nodegroup",
130
+ name=f"{cluster_name}/{nodegroup_name}",
131
+ region=self.region,
132
+ tags=tags,
133
+ config_hash=compute_config_hash(nodegroup),
134
+ created_at=created_at,
135
+ raw_config=nodegroup,
136
+ )
137
+ resources.append(resource)
138
+
139
+ except Exception as e:
140
+ self.logger.debug(f"Error processing node group {nodegroup_name}: {e}")
141
+ continue
142
+
143
+ except Exception as e:
144
+ self.logger.debug(f"Error collecting node groups for cluster {cluster_name}: {e}")
145
+
146
+ return resources
147
+
148
+ def _collect_fargate_profiles(self, cluster_names: List[str]) -> List[Resource]:
149
+ """Collect EKS Fargate profiles for given clusters.
150
+
151
+ Args:
152
+ cluster_names: List of cluster names to collect Fargate profiles from
153
+
154
+ Returns:
155
+ List of Fargate profile resources
156
+ """
157
+ resources = []
158
+ client = self._create_client()
159
+
160
+ for cluster_name in cluster_names:
161
+ try:
162
+ paginator = client.get_paginator("list_fargate_profiles")
163
+ for page in paginator.paginate(clusterName=cluster_name):
164
+ for profile_name in page.get("fargateProfileNames", []):
165
+ try:
166
+ # Get detailed Fargate profile info
167
+ profile_response = client.describe_fargate_profile(
168
+ clusterName=cluster_name, fargateProfileName=profile_name
169
+ )
170
+ profile = profile_response.get("fargateProfile", {})
171
+
172
+ profile_arn = profile.get("fargateProfileArn", "")
173
+
174
+ # Extract tags
175
+ tags = profile.get("tags", {})
176
+
177
+ # Extract creation date
178
+ created_at = profile.get("createdAt")
179
+
180
+ # Create resource
181
+ resource = Resource(
182
+ arn=profile_arn,
183
+ resource_type="AWS::EKS::FargateProfile",
184
+ name=f"{cluster_name}/{profile_name}",
185
+ region=self.region,
186
+ tags=tags,
187
+ config_hash=compute_config_hash(profile),
188
+ created_at=created_at,
189
+ raw_config=profile,
190
+ )
191
+ resources.append(resource)
192
+
193
+ except Exception as e:
194
+ self.logger.debug(f"Error processing Fargate profile {profile_name}: {e}")
195
+ continue
196
+
197
+ except Exception as e:
198
+ self.logger.debug(f"Error collecting Fargate profiles for cluster {cluster_name}: {e}")
199
+
200
+ return resources