terraformgraph 1.0.1__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.
@@ -0,0 +1,795 @@
1
+ """
2
+ AWS Icon Mapper
3
+
4
+ Maps Terraform resource types to AWS architecture icons.
5
+ """
6
+
7
+ import base64
8
+ from pathlib import Path
9
+ from typing import Dict, Optional, Tuple
10
+
11
+ # Mapping from Terraform resource type to icon info
12
+ # Format: resource_type -> (category, icon_name)
13
+ TERRAFORM_TO_ICON: Dict[str, Tuple[str, str]] = {
14
+ # ==========================================================================
15
+ # NETWORKING & CONTENT DELIVERY
16
+ # ==========================================================================
17
+ 'aws_vpc': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-Virtual-Private-Cloud'),
18
+ 'aws_subnet': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-Virtual-Private-Cloud'),
19
+ 'aws_internet_gateway': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-Virtual-Private-Cloud'),
20
+ 'aws_nat_gateway': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-Virtual-Private-Cloud'),
21
+ 'aws_route_table': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-Virtual-Private-Cloud'),
22
+ 'aws_route': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-Virtual-Private-Cloud'),
23
+ 'aws_route_table_association': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-Virtual-Private-Cloud'),
24
+ 'aws_eip': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-Virtual-Private-Cloud'),
25
+ 'aws_vpc_endpoint': ('Arch_Networking-Content-Delivery', 'Arch_AWS-PrivateLink'),
26
+ 'aws_vpc_peering_connection': ('Arch_Networking-Content-Delivery', 'Arch_AWS-Transit-Gateway'),
27
+ 'aws_transit_gateway': ('Arch_Networking-Content-Delivery', 'Arch_AWS-Transit-Gateway'),
28
+ 'aws_transit_gateway_attachment': ('Arch_Networking-Content-Delivery', 'Arch_AWS-Transit-Gateway'),
29
+ 'aws_vpn_gateway': ('Arch_Networking-Content-Delivery', 'Arch_AWS-Site-to-Site-VPN'),
30
+ 'aws_vpn_connection': ('Arch_Networking-Content-Delivery', 'Arch_AWS-Site-to-Site-VPN'),
31
+ 'aws_customer_gateway': ('Arch_Networking-Content-Delivery', 'Arch_AWS-Site-to-Site-VPN'),
32
+ 'aws_dx_connection': ('Arch_Networking-Content-Delivery', 'Arch_AWS-Direct-Connect'),
33
+ 'aws_vpc_lattice_service': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-VPC-Lattice'),
34
+
35
+ # Load Balancing
36
+ 'aws_lb': ('Arch_Networking-Content-Delivery', 'Arch_Elastic-Load-Balancing'),
37
+ 'aws_alb': ('Arch_Networking-Content-Delivery', 'Arch_Elastic-Load-Balancing'),
38
+ 'aws_elb': ('Arch_Networking-Content-Delivery', 'Arch_Elastic-Load-Balancing'),
39
+ 'aws_lb_target_group': ('Arch_Networking-Content-Delivery', 'Arch_Elastic-Load-Balancing'),
40
+ 'aws_lb_listener': ('Arch_Networking-Content-Delivery', 'Arch_Elastic-Load-Balancing'),
41
+ 'aws_lb_listener_rule': ('Arch_Networking-Content-Delivery', 'Arch_Elastic-Load-Balancing'),
42
+
43
+ # DNS & CDN
44
+ 'aws_route53_zone': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-Route-53'),
45
+ 'aws_route53_record': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-Route-53'),
46
+ 'aws_route53_health_check': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-Route-53'),
47
+ 'aws_cloudfront_distribution': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-CloudFront'),
48
+ 'aws_cloudfront_origin_access_identity': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-CloudFront'),
49
+ 'aws_cloudfront_origin_access_control': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-CloudFront'),
50
+ 'aws_cloudfront_function': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-CloudFront'),
51
+ 'aws_cloudfront_cache_policy': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-CloudFront'),
52
+
53
+ # API Gateway
54
+ 'aws_api_gateway_rest_api': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-API-Gateway'),
55
+ 'aws_api_gateway_resource': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-API-Gateway'),
56
+ 'aws_api_gateway_method': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-API-Gateway'),
57
+ 'aws_api_gateway_integration': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-API-Gateway'),
58
+ 'aws_api_gateway_deployment': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-API-Gateway'),
59
+ 'aws_api_gateway_stage': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-API-Gateway'),
60
+ 'aws_apigatewayv2_api': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-API-Gateway'),
61
+ 'aws_apigatewayv2_stage': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-API-Gateway'),
62
+ 'aws_apigatewayv2_route': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-API-Gateway'),
63
+ 'aws_apigatewayv2_integration': ('Arch_Networking-Content-Delivery', 'Arch_Amazon-API-Gateway'),
64
+
65
+ # Global Accelerator
66
+ 'aws_globalaccelerator_accelerator': ('Arch_Networking-Content-Delivery', 'Arch_AWS-Global-Accelerator'),
67
+ 'aws_globalaccelerator_listener': ('Arch_Networking-Content-Delivery', 'Arch_AWS-Global-Accelerator'),
68
+
69
+ # App Mesh
70
+ 'aws_appmesh_mesh': ('Arch_Networking-Content-Delivery', 'Arch_AWS-App-Mesh'),
71
+ 'aws_appmesh_virtual_service': ('Arch_Networking-Content-Delivery', 'Arch_AWS-App-Mesh'),
72
+
73
+ # Cloud Map
74
+ 'aws_service_discovery_service': ('Arch_Networking-Content-Delivery', 'Arch_AWS-Cloud-Map'),
75
+ 'aws_service_discovery_private_dns_namespace': ('Arch_Networking-Content-Delivery', 'Arch_AWS-Cloud-Map'),
76
+
77
+ # ==========================================================================
78
+ # COMPUTE
79
+ # ==========================================================================
80
+ 'aws_instance': ('Arch_Compute', 'Arch_Amazon-EC2'),
81
+ 'aws_launch_template': ('Arch_Compute', 'Arch_Amazon-EC2'),
82
+ 'aws_launch_configuration': ('Arch_Compute', 'Arch_Amazon-EC2'),
83
+ 'aws_ami': ('Arch_Compute', 'Arch_Amazon-EC2-Image-Builder'),
84
+ 'aws_autoscaling_group': ('Arch_Compute', 'Arch_Amazon-EC2-Auto-Scaling'),
85
+ 'aws_autoscaling_policy': ('Arch_Compute', 'Arch_Amazon-EC2-Auto-Scaling'),
86
+ 'aws_spot_instance_request': ('Arch_Compute', 'Arch_Amazon-EC2'),
87
+ 'aws_spot_fleet_request': ('Arch_Compute', 'Arch_Amazon-EC2'),
88
+
89
+ # Lambda
90
+ 'aws_lambda_function': ('Arch_Compute', 'Arch_AWS-Lambda'),
91
+ 'aws_lambda_layer_version': ('Arch_Compute', 'Arch_AWS-Lambda'),
92
+ 'aws_lambda_permission': ('Arch_Compute', 'Arch_AWS-Lambda'),
93
+ 'aws_lambda_event_source_mapping': ('Arch_Compute', 'Arch_AWS-Lambda'),
94
+ 'aws_lambda_alias': ('Arch_Compute', 'Arch_AWS-Lambda'),
95
+ 'aws_lambda_function_url': ('Arch_Compute', 'Arch_AWS-Lambda'),
96
+
97
+ # Batch
98
+ 'aws_batch_compute_environment': ('Arch_Compute', 'Arch_AWS-Batch'),
99
+ 'aws_batch_job_queue': ('Arch_Compute', 'Arch_AWS-Batch'),
100
+ 'aws_batch_job_definition': ('Arch_Compute', 'Arch_AWS-Batch'),
101
+
102
+ # Elastic Beanstalk
103
+ 'aws_elastic_beanstalk_application': ('Arch_Compute', 'Arch_AWS-Elastic-Beanstalk'),
104
+ 'aws_elastic_beanstalk_environment': ('Arch_Compute', 'Arch_AWS-Elastic-Beanstalk'),
105
+
106
+ # Lightsail
107
+ 'aws_lightsail_instance': ('Arch_Compute', 'Arch_Amazon-Lightsail'),
108
+ 'aws_lightsail_container_service': ('Arch_Compute', 'Arch_Amazon-Lightsail'),
109
+
110
+ # App Runner
111
+ 'aws_apprunner_service': ('Arch_Compute', 'Arch_AWS-App-Runner'),
112
+
113
+ # ==========================================================================
114
+ # CONTAINERS
115
+ # ==========================================================================
116
+ 'aws_ecs_cluster': ('Arch_Containers', 'Arch_Amazon-Elastic-Container-Service'),
117
+ 'aws_ecs_service': ('Arch_Containers', 'Arch_Amazon-Elastic-Container-Service'),
118
+ 'aws_ecs_task_definition': ('Arch_Containers', 'Arch_Amazon-Elastic-Container-Service'),
119
+ 'aws_ecs_capacity_provider': ('Arch_Containers', 'Arch_Amazon-Elastic-Container-Service'),
120
+ 'aws_ecr_repository': ('Arch_Containers', 'Arch_Amazon-Elastic-Container-Registry'),
121
+ 'aws_ecr_lifecycle_policy': ('Arch_Containers', 'Arch_Amazon-Elastic-Container-Registry'),
122
+ 'aws_eks_cluster': ('Arch_Containers', 'Arch_Amazon-Elastic-Kubernetes-Service'),
123
+ 'aws_eks_node_group': ('Arch_Containers', 'Arch_Amazon-Elastic-Kubernetes-Service'),
124
+ 'aws_eks_fargate_profile': ('Arch_Containers', 'Arch_AWS-Fargate'),
125
+ 'aws_eks_addon': ('Arch_Containers', 'Arch_Amazon-Elastic-Kubernetes-Service'),
126
+
127
+ # ==========================================================================
128
+ # STORAGE
129
+ # ==========================================================================
130
+ 'aws_s3_bucket': ('Arch_Storage', 'Arch_Amazon-Simple-Storage-Service'),
131
+ 'aws_s3_bucket_notification': ('Arch_Storage', 'Arch_Amazon-Simple-Storage-Service'),
132
+ 'aws_s3_bucket_policy': ('Arch_Storage', 'Arch_Amazon-Simple-Storage-Service'),
133
+ 'aws_s3_bucket_versioning': ('Arch_Storage', 'Arch_Amazon-Simple-Storage-Service'),
134
+ 'aws_s3_bucket_lifecycle_configuration': ('Arch_Storage', 'Arch_Amazon-Simple-Storage-Service'),
135
+ 'aws_s3_bucket_replication_configuration': ('Arch_Storage', 'Arch_Amazon-Simple-Storage-Service'),
136
+ 'aws_s3_bucket_server_side_encryption_configuration': ('Arch_Storage', 'Arch_Amazon-Simple-Storage-Service'),
137
+ 'aws_s3_object': ('Arch_Storage', 'Arch_Amazon-Simple-Storage-Service'),
138
+ 'aws_s3_bucket_public_access_block': ('Arch_Storage', 'Arch_Amazon-Simple-Storage-Service'),
139
+
140
+ # S3 Glacier
141
+ 'aws_glacier_vault': ('Arch_Storage', 'Arch_Amazon-Simple-Storage-Service-Glacier'),
142
+
143
+ # EBS
144
+ 'aws_ebs_volume': ('Arch_Storage', 'Arch_Amazon-Elastic-Block-Store'),
145
+ 'aws_ebs_snapshot': ('Arch_Storage', 'Arch_Amazon-Elastic-Block-Store'),
146
+ 'aws_volume_attachment': ('Arch_Storage', 'Arch_Amazon-Elastic-Block-Store'),
147
+
148
+ # EFS
149
+ 'aws_efs_file_system': ('Arch_Storage', 'Arch_Amazon-EFS'),
150
+ 'aws_efs_mount_target': ('Arch_Storage', 'Arch_Amazon-EFS'),
151
+ 'aws_efs_access_point': ('Arch_Storage', 'Arch_Amazon-EFS'),
152
+
153
+ # FSx
154
+ 'aws_fsx_lustre_file_system': ('Arch_Storage', 'Arch_Amazon-FSx-for-Lustre'),
155
+ 'aws_fsx_windows_file_system': ('Arch_Storage', 'Arch_Amazon-FSx-for-WFS'),
156
+ 'aws_fsx_ontap_file_system': ('Arch_Storage', 'Arch_Amazon-FSx-for-NetApp-ONTAP'),
157
+ 'aws_fsx_openzfs_file_system': ('Arch_Storage', 'Arch_Amazon-FSx-for-OpenZFS'),
158
+
159
+ # Storage Gateway
160
+ 'aws_storagegateway_gateway': ('Arch_Storage', 'Arch_AWS-Storage-Gateway'),
161
+
162
+ # Backup
163
+ 'aws_backup_vault': ('Arch_Storage', 'Arch_AWS-Backup'),
164
+ 'aws_backup_plan': ('Arch_Storage', 'Arch_AWS-Backup'),
165
+
166
+ # ==========================================================================
167
+ # DATABASE
168
+ # ==========================================================================
169
+ 'aws_dynamodb_table': ('Arch_Database', 'Arch_Amazon-DynamoDB'),
170
+ 'aws_dynamodb_global_table': ('Arch_Database', 'Arch_Amazon-DynamoDB'),
171
+
172
+ # RDS
173
+ 'aws_rds_cluster': ('Arch_Database', 'Arch_Amazon-Aurora'),
174
+ 'aws_rds_cluster_instance': ('Arch_Database', 'Arch_Amazon-Aurora'),
175
+ 'aws_db_instance': ('Arch_Database', 'Arch_Amazon-RDS'),
176
+ 'aws_db_subnet_group': ('Arch_Database', 'Arch_Amazon-RDS'),
177
+ 'aws_db_parameter_group': ('Arch_Database', 'Arch_Amazon-RDS'),
178
+ 'aws_db_option_group': ('Arch_Database', 'Arch_Amazon-RDS'),
179
+ 'aws_db_proxy': ('Arch_Database', 'Arch_Amazon-RDS'),
180
+
181
+ # ElastiCache
182
+ 'aws_elasticache_cluster': ('Arch_Database', 'Arch_Amazon-ElastiCache'),
183
+ 'aws_elasticache_replication_group': ('Arch_Database', 'Arch_Amazon-ElastiCache'),
184
+ 'aws_elasticache_subnet_group': ('Arch_Database', 'Arch_Amazon-ElastiCache'),
185
+ 'aws_elasticache_parameter_group': ('Arch_Database', 'Arch_Amazon-ElastiCache'),
186
+
187
+ # MemoryDB
188
+ 'aws_memorydb_cluster': ('Arch_Database', 'Arch_Amazon-MemoryDB'),
189
+
190
+ # DocumentDB
191
+ 'aws_docdb_cluster': ('Arch_Database', 'Arch_Amazon-DocumentDB'),
192
+ 'aws_docdb_cluster_instance': ('Arch_Database', 'Arch_Amazon-DocumentDB'),
193
+
194
+ # Neptune
195
+ 'aws_neptune_cluster': ('Arch_Database', 'Arch_Amazon-Neptune'),
196
+ 'aws_neptune_cluster_instance': ('Arch_Database', 'Arch_Amazon-Neptune'),
197
+
198
+ # Keyspaces (Cassandra)
199
+ 'aws_keyspaces_keyspace': ('Arch_Database', 'Arch_Amazon-Keyspaces'),
200
+ 'aws_keyspaces_table': ('Arch_Database', 'Arch_Amazon-Keyspaces'),
201
+
202
+ # Timestream
203
+ 'aws_timestreamwrite_database': ('Arch_Database', 'Arch_Amazon-Timestream'),
204
+ 'aws_timestreamwrite_table': ('Arch_Database', 'Arch_Amazon-Timestream'),
205
+
206
+ # QLDB
207
+ 'aws_qldb_ledger': ('Arch_Database', 'Arch_Amazon-Quantum-Ledger-Database'),
208
+
209
+ # Redshift
210
+ 'aws_redshift_cluster': ('Arch_Database', 'Arch_Amazon-Redshift'),
211
+ 'aws_redshiftserverless_namespace': ('Arch_Database', 'Arch_Amazon-Redshift'),
212
+ 'aws_redshiftserverless_workgroup': ('Arch_Database', 'Arch_Amazon-Redshift'),
213
+
214
+ # ==========================================================================
215
+ # APPLICATION INTEGRATION
216
+ # ==========================================================================
217
+ 'aws_sqs_queue': ('Arch_App-Integration', 'Arch_Amazon-Simple-Queue-Service'),
218
+ 'aws_sqs_queue_policy': ('Arch_App-Integration', 'Arch_Amazon-Simple-Queue-Service'),
219
+
220
+ 'aws_sns_topic': ('Arch_App-Integration', 'Arch_Amazon-Simple-Notification-Service'),
221
+ 'aws_sns_topic_subscription': ('Arch_App-Integration', 'Arch_Amazon-Simple-Notification-Service'),
222
+ 'aws_sns_topic_policy': ('Arch_App-Integration', 'Arch_Amazon-Simple-Notification-Service'),
223
+
224
+ 'aws_sfn_state_machine': ('Arch_App-Integration', 'Arch_AWS-Step-Functions'),
225
+ 'aws_sfn_activity': ('Arch_App-Integration', 'Arch_AWS-Step-Functions'),
226
+
227
+ # EventBridge
228
+ 'aws_cloudwatch_event_rule': ('Arch_App-Integration', 'Arch_Amazon-EventBridge'),
229
+ 'aws_cloudwatch_event_target': ('Arch_App-Integration', 'Arch_Amazon-EventBridge'),
230
+ 'aws_cloudwatch_event_bus': ('Arch_App-Integration', 'Arch_Amazon-EventBridge'),
231
+ 'aws_cloudwatch_event_archive': ('Arch_App-Integration', 'Arch_Amazon-EventBridge'),
232
+ 'aws_scheduler_schedule': ('Arch_App-Integration', 'Arch_Amazon-EventBridge'),
233
+
234
+ # AppSync
235
+ 'aws_appsync_graphql_api': ('Arch_App-Integration', 'Arch_AWS-AppSync'),
236
+ 'aws_appsync_datasource': ('Arch_App-Integration', 'Arch_AWS-AppSync'),
237
+ 'aws_appsync_resolver': ('Arch_App-Integration', 'Arch_AWS-AppSync'),
238
+
239
+ # MQ
240
+ 'aws_mq_broker': ('Arch_App-Integration', 'Arch_Amazon-MQ'),
241
+ 'aws_mq_configuration': ('Arch_App-Integration', 'Arch_Amazon-MQ'),
242
+
243
+ # AppFlow
244
+ 'aws_appflow_flow': ('Arch_App-Integration', 'Arch_Amazon-AppFlow'),
245
+
246
+ # ==========================================================================
247
+ # ANALYTICS
248
+ # ==========================================================================
249
+ 'aws_kinesis_stream': ('Arch_Analytics', 'Arch_Amazon-Kinesis-Data-Streams'),
250
+ 'aws_kinesis_firehose_delivery_stream': ('Arch_Analytics', 'Arch_Amazon-Data-Firehose'),
251
+ 'aws_kinesis_analytics_application': ('Arch_Analytics', 'Arch_Amazon-Managed-Service-for-Apache-Flink'),
252
+ 'aws_kinesisanalyticsv2_application': ('Arch_Analytics', 'Arch_Amazon-Managed-Service-for-Apache-Flink'),
253
+
254
+ # Athena
255
+ 'aws_athena_workgroup': ('Arch_Analytics', 'Arch_Amazon-Athena'),
256
+ 'aws_athena_database': ('Arch_Analytics', 'Arch_Amazon-Athena'),
257
+ 'aws_athena_named_query': ('Arch_Analytics', 'Arch_Amazon-Athena'),
258
+
259
+ # Glue
260
+ 'aws_glue_catalog_database': ('Arch_Analytics', 'Arch_AWS-Glue'),
261
+ 'aws_glue_catalog_table': ('Arch_Analytics', 'Arch_AWS-Glue'),
262
+ 'aws_glue_crawler': ('Arch_Analytics', 'Arch_AWS-Glue'),
263
+ 'aws_glue_job': ('Arch_Analytics', 'Arch_AWS-Glue'),
264
+ 'aws_glue_trigger': ('Arch_Analytics', 'Arch_AWS-Glue'),
265
+ 'aws_glue_workflow': ('Arch_Analytics', 'Arch_AWS-Glue'),
266
+
267
+ # EMR
268
+ 'aws_emr_cluster': ('Arch_Analytics', 'Arch_Amazon-EMR'),
269
+ 'aws_emr_studio': ('Arch_Analytics', 'Arch_Amazon-EMR'),
270
+ 'aws_emrserverless_application': ('Arch_Analytics', 'Arch_Amazon-EMR'),
271
+
272
+ # OpenSearch
273
+ 'aws_opensearch_domain': ('Arch_Analytics', 'Arch_Amazon-OpenSearch-Service'),
274
+ 'aws_elasticsearch_domain': ('Arch_Analytics', 'Arch_Amazon-OpenSearch-Service'),
275
+
276
+ # MSK (Kafka)
277
+ 'aws_msk_cluster': ('Arch_Analytics', 'Arch_Amazon-Managed-Streaming-for-Apache-Kafka'),
278
+ 'aws_msk_configuration': ('Arch_Analytics', 'Arch_Amazon-Managed-Streaming-for-Apache-Kafka'),
279
+ 'aws_mskconnect_connector': ('Arch_Analytics', 'Arch_Amazon-Managed-Streaming-for-Apache-Kafka'),
280
+
281
+ # QuickSight
282
+ 'aws_quicksight_data_source': ('Arch_Analytics', 'Arch_Amazon-QuickSight'),
283
+ 'aws_quicksight_dataset': ('Arch_Analytics', 'Arch_Amazon-QuickSight'),
284
+
285
+ # Lake Formation
286
+ 'aws_lakeformation_resource': ('Arch_Analytics', 'Arch_AWS-Lake-Formation'),
287
+ 'aws_lakeformation_permissions': ('Arch_Analytics', 'Arch_AWS-Lake-Formation'),
288
+
289
+ # Data Exchange
290
+ 'aws_dataexchange_data_set': ('Arch_Analytics', 'Arch_AWS-Data-Exchange'),
291
+
292
+ # ==========================================================================
293
+ # SECURITY & IDENTITY
294
+ # ==========================================================================
295
+ 'aws_security_group': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Network-Firewall'),
296
+ 'aws_security_group_rule': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Network-Firewall'),
297
+ 'aws_vpc_security_group_ingress_rule': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Network-Firewall'),
298
+ 'aws_vpc_security_group_egress_rule': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Network-Firewall'),
299
+ 'aws_network_acl': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Network-Firewall'),
300
+ 'aws_networkfirewall_firewall': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Network-Firewall'),
301
+ 'aws_networkfirewall_firewall_policy': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Network-Firewall'),
302
+
303
+ # Cognito
304
+ 'aws_cognito_user_pool': ('Arch_Security-Identity-Compliance', 'Arch_Amazon-Cognito'),
305
+ 'aws_cognito_user_pool_client': ('Arch_Security-Identity-Compliance', 'Arch_Amazon-Cognito'),
306
+ 'aws_cognito_user_pool_domain': ('Arch_Security-Identity-Compliance', 'Arch_Amazon-Cognito'),
307
+ 'aws_cognito_identity_pool': ('Arch_Security-Identity-Compliance', 'Arch_Amazon-Cognito'),
308
+
309
+ # KMS
310
+ 'aws_kms_key': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Key-Management-Service'),
311
+ 'aws_kms_alias': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Key-Management-Service'),
312
+ 'aws_kms_grant': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Key-Management-Service'),
313
+
314
+ # Secrets Manager
315
+ 'aws_secretsmanager_secret': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Secrets-Manager'),
316
+ 'aws_secretsmanager_secret_version': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Secrets-Manager'),
317
+ 'aws_secretsmanager_secret_rotation': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Secrets-Manager'),
318
+
319
+ # IAM
320
+ 'aws_iam_role': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Identity-and-Access-Management'),
321
+ 'aws_iam_policy': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Identity-and-Access-Management'),
322
+ 'aws_iam_role_policy': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Identity-and-Access-Management'),
323
+ 'aws_iam_role_policy_attachment': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Identity-and-Access-Management'),
324
+ 'aws_iam_user': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Identity-and-Access-Management'),
325
+ 'aws_iam_group': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Identity-and-Access-Management'),
326
+ 'aws_iam_instance_profile': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Identity-and-Access-Management'),
327
+ 'aws_iam_openid_connect_provider': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Identity-and-Access-Management'),
328
+ 'aws_iam_saml_provider': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Identity-and-Access-Management'),
329
+
330
+ # SSO / Identity Center
331
+ 'aws_ssoadmin_permission_set': ('Arch_Security-Identity-Compliance', 'Arch_AWS-IAM-Identity-Center'),
332
+ 'aws_identitystore_user': ('Arch_Security-Identity-Compliance', 'Arch_AWS-IAM-Identity-Center'),
333
+
334
+ # ACM
335
+ 'aws_acm_certificate': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Certificate-Manager'),
336
+ 'aws_acm_certificate_validation': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Certificate-Manager'),
337
+ 'aws_acmpca_certificate_authority': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Private-Certificate-Authority'),
338
+
339
+ # WAF
340
+ 'aws_wafv2_web_acl': ('Arch_Security-Identity-Compliance', 'Arch_AWS-WAF'),
341
+ 'aws_wafv2_web_acl_association': ('Arch_Security-Identity-Compliance', 'Arch_AWS-WAF'),
342
+ 'aws_wafv2_rule_group': ('Arch_Security-Identity-Compliance', 'Arch_AWS-WAF'),
343
+ 'aws_wafv2_ip_set': ('Arch_Security-Identity-Compliance', 'Arch_AWS-WAF'),
344
+ 'aws_wafv2_regex_pattern_set': ('Arch_Security-Identity-Compliance', 'Arch_AWS-WAF'),
345
+
346
+ # Shield
347
+ 'aws_shield_protection': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Shield'),
348
+
349
+ # GuardDuty
350
+ 'aws_guardduty_detector': ('Arch_Security-Identity-Compliance', 'Arch_Amazon-GuardDuty'),
351
+ 'aws_guardduty_member': ('Arch_Security-Identity-Compliance', 'Arch_Amazon-GuardDuty'),
352
+
353
+ # Security Hub
354
+ 'aws_securityhub_account': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Security-Hub'),
355
+ 'aws_securityhub_member': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Security-Hub'),
356
+
357
+ # Macie
358
+ 'aws_macie2_account': ('Arch_Security-Identity-Compliance', 'Arch_Amazon-Macie'),
359
+ 'aws_macie2_classification_job': ('Arch_Security-Identity-Compliance', 'Arch_Amazon-Macie'),
360
+
361
+ # Inspector
362
+ 'aws_inspector2_enabler': ('Arch_Security-Identity-Compliance', 'Arch_Amazon-Inspector'),
363
+
364
+ # Detective
365
+ 'aws_detective_graph': ('Arch_Security-Identity-Compliance', 'Arch_Amazon-Detective'),
366
+
367
+ # Firewall Manager
368
+ 'aws_fms_policy': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Firewall-Manager'),
369
+
370
+ # RAM
371
+ 'aws_ram_resource_share': ('Arch_Security-Identity-Compliance', 'Arch_AWS-Resource-Access-Manager'),
372
+
373
+ # ==========================================================================
374
+ # MANAGEMENT & GOVERNANCE
375
+ # ==========================================================================
376
+ 'aws_cloudwatch_log_group': ('Arch_Management-Governance', 'Arch_Amazon-CloudWatch'),
377
+ 'aws_cloudwatch_metric_alarm': ('Arch_Management-Governance', 'Arch_Amazon-CloudWatch'),
378
+ 'aws_cloudwatch_dashboard': ('Arch_Management-Governance', 'Arch_Amazon-CloudWatch'),
379
+ 'aws_cloudwatch_log_stream': ('Arch_Management-Governance', 'Arch_Amazon-CloudWatch'),
380
+ 'aws_cloudwatch_log_metric_filter': ('Arch_Management-Governance', 'Arch_Amazon-CloudWatch'),
381
+ 'aws_cloudwatch_composite_alarm': ('Arch_Management-Governance', 'Arch_Amazon-CloudWatch'),
382
+
383
+ 'aws_cloudtrail': ('Arch_Management-Governance', 'Arch_AWS-CloudTrail'),
384
+ 'aws_cloudtrail_event_data_store': ('Arch_Management-Governance', 'Arch_AWS-CloudTrail'),
385
+
386
+ 'aws_config_config_rule': ('Arch_Management-Governance', 'Arch_AWS-Config'),
387
+ 'aws_config_configuration_recorder': ('Arch_Management-Governance', 'Arch_AWS-Config'),
388
+ 'aws_config_delivery_channel': ('Arch_Management-Governance', 'Arch_AWS-Config'),
389
+
390
+ # Systems Manager
391
+ 'aws_ssm_parameter': ('Arch_Management-Governance', 'Arch_AWS-Systems-Manager'),
392
+ 'aws_ssm_document': ('Arch_Management-Governance', 'Arch_AWS-Systems-Manager'),
393
+ 'aws_ssm_maintenance_window': ('Arch_Management-Governance', 'Arch_AWS-Systems-Manager'),
394
+ 'aws_ssm_patch_baseline': ('Arch_Management-Governance', 'Arch_AWS-Systems-Manager'),
395
+ 'aws_ssm_association': ('Arch_Management-Governance', 'Arch_AWS-Systems-Manager'),
396
+
397
+ # Organizations
398
+ 'aws_organizations_organization': ('Arch_Management-Governance', 'Arch_AWS-Organizations'),
399
+ 'aws_organizations_account': ('Arch_Management-Governance', 'Arch_AWS-Organizations'),
400
+ 'aws_organizations_organizational_unit': ('Arch_Management-Governance', 'Arch_AWS-Organizations'),
401
+ 'aws_organizations_policy': ('Arch_Management-Governance', 'Arch_AWS-Organizations'),
402
+
403
+ # Control Tower
404
+ 'aws_controltower_control': ('Arch_Management-Governance', 'Arch_AWS-Control-Tower'),
405
+
406
+ # Service Catalog
407
+ 'aws_servicecatalog_portfolio': ('Arch_Management-Governance', 'Arch_AWS-Service-Catalog'),
408
+ 'aws_servicecatalog_product': ('Arch_Management-Governance', 'Arch_AWS-Service-Catalog'),
409
+
410
+ # CloudFormation
411
+ 'aws_cloudformation_stack': ('Arch_Management-Governance', 'Arch_AWS-CloudFormation'),
412
+ 'aws_cloudformation_stack_set': ('Arch_Management-Governance', 'Arch_AWS-CloudFormation'),
413
+
414
+ # X-Ray
415
+ 'aws_xray_sampling_rule': ('Arch_Developer-Tools', 'Arch_AWS-X-Ray'),
416
+ 'aws_xray_group': ('Arch_Developer-Tools', 'Arch_AWS-X-Ray'),
417
+
418
+ # ==========================================================================
419
+ # DEVELOPER TOOLS
420
+ # ==========================================================================
421
+ 'aws_codecommit_repository': ('Arch_Developer-Tools', 'Arch_AWS-CodeCommit'),
422
+ 'aws_codebuild_project': ('Arch_Developer-Tools', 'Arch_AWS-CodeBuild'),
423
+ 'aws_codepipeline': ('Arch_Developer-Tools', 'Arch_AWS-CodePipeline'),
424
+ 'aws_codedeploy_app': ('Arch_Developer-Tools', 'Arch_AWS-CodeDeploy'),
425
+ 'aws_codedeploy_deployment_group': ('Arch_Developer-Tools', 'Arch_AWS-CodeDeploy'),
426
+ 'aws_codeartifact_domain': ('Arch_Developer-Tools', 'Arch_AWS-CodeArtifact'),
427
+ 'aws_codeartifact_repository': ('Arch_Developer-Tools', 'Arch_AWS-CodeArtifact'),
428
+ 'aws_cloud9_environment_ec2': ('Arch_Developer-Tools', 'Arch_AWS-Cloud9'),
429
+ 'aws_codecatalyst_dev_environment': ('Arch_Developer-Tools', 'Arch_Amazon-CodeCatalyst'),
430
+
431
+ # ==========================================================================
432
+ # COST MANAGEMENT
433
+ # ==========================================================================
434
+ 'aws_budgets_budget': ('Arch_Cloud-Financial-Management', 'Arch_AWS-Budgets'),
435
+ 'aws_budgets_budget_action': ('Arch_Cloud-Financial-Management', 'Arch_AWS-Budgets'),
436
+ 'aws_ce_cost_category': ('Arch_Cloud-Financial-Management', 'Arch_AWS-Cost-Explorer'),
437
+ 'aws_ce_anomaly_monitor': ('Arch_Cloud-Financial-Management', 'Arch_AWS-Cost-Explorer'),
438
+
439
+ # ==========================================================================
440
+ # BUSINESS APPLICATIONS
441
+ # ==========================================================================
442
+ 'aws_ses_domain_identity': ('Arch_Business-Applications', 'Arch_Amazon-Simple-Email-Service'),
443
+ 'aws_ses_configuration_set': ('Arch_Business-Applications', 'Arch_Amazon-Simple-Email-Service'),
444
+ 'aws_ses_email_identity': ('Arch_Business-Applications', 'Arch_Amazon-Simple-Email-Service'),
445
+ 'aws_sesv2_email_identity': ('Arch_Business-Applications', 'Arch_Amazon-Simple-Email-Service'),
446
+ 'aws_sesv2_configuration_set': ('Arch_Business-Applications', 'Arch_Amazon-Simple-Email-Service'),
447
+
448
+ # Connect
449
+ 'aws_connect_instance': ('Arch_Business-Applications', 'Arch_Amazon-Connect'),
450
+ 'aws_connect_contact_flow': ('Arch_Business-Applications', 'Arch_Amazon-Connect'),
451
+
452
+ # Pinpoint
453
+ 'aws_pinpoint_app': ('Arch_Business-Applications', 'Arch_Amazon-Pinpoint'),
454
+ 'aws_pinpoint_email_channel': ('Arch_Business-Applications', 'Arch_Amazon-Pinpoint'),
455
+
456
+ # Chime
457
+ 'aws_chime_voice_connector': ('Arch_Business-Applications', 'Arch_Amazon-Chime'),
458
+
459
+ # WorkSpaces
460
+ 'aws_workspaces_workspace': ('Arch_End-User-Computing', 'Arch_Amazon-WorkSpaces-Family'),
461
+ 'aws_workspaces_directory': ('Arch_End-User-Computing', 'Arch_Amazon-WorkSpaces-Family'),
462
+
463
+ # AppStream
464
+ 'aws_appstream_fleet': ('Arch_End-User-Computing', 'Arch_Amazon-AppStream-2'),
465
+ 'aws_appstream_stack': ('Arch_End-User-Computing', 'Arch_Amazon-AppStream-2'),
466
+
467
+ # ==========================================================================
468
+ # AI/ML
469
+ # ==========================================================================
470
+ 'aws_bedrockagent_knowledge_base': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Bedrock'),
471
+ 'aws_bedrockagent_agent': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Bedrock'),
472
+ 'aws_bedrock_model_invocation_logging_configuration': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Bedrock'),
473
+
474
+ 'aws_sagemaker_notebook_instance': ('Arch_Artificial-Intelligence', 'Arch_Amazon-SageMaker'),
475
+ 'aws_sagemaker_endpoint': ('Arch_Artificial-Intelligence', 'Arch_Amazon-SageMaker'),
476
+ 'aws_sagemaker_model': ('Arch_Artificial-Intelligence', 'Arch_Amazon-SageMaker'),
477
+ 'aws_sagemaker_endpoint_configuration': ('Arch_Artificial-Intelligence', 'Arch_Amazon-SageMaker'),
478
+ 'aws_sagemaker_domain': ('Arch_Artificial-Intelligence', 'Arch_Amazon-SageMaker'),
479
+ 'aws_sagemaker_feature_group': ('Arch_Artificial-Intelligence', 'Arch_Amazon-SageMaker'),
480
+ 'aws_sagemaker_pipeline': ('Arch_Artificial-Intelligence', 'Arch_Amazon-SageMaker'),
481
+
482
+ # Comprehend
483
+ 'aws_comprehend_entity_recognizer': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Comprehend'),
484
+ 'aws_comprehend_document_classifier': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Comprehend'),
485
+
486
+ # Rekognition
487
+ 'aws_rekognition_collection': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Rekognition'),
488
+ 'aws_rekognition_project': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Rekognition'),
489
+
490
+ # Textract
491
+ 'aws_textract_adapter': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Textract'),
492
+
493
+ # Polly
494
+ 'aws_polly_lexicon': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Polly'),
495
+
496
+ # Transcribe
497
+ 'aws_transcribe_vocabulary': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Transcribe'),
498
+ 'aws_transcribe_language_model': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Transcribe'),
499
+
500
+ # Translate
501
+ 'aws_translate_terminology': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Translate'),
502
+
503
+ # Lex
504
+ 'aws_lex_bot': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Lex'),
505
+ 'aws_lexv2models_bot': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Lex'),
506
+
507
+ # Kendra
508
+ 'aws_kendra_index': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Kendra'),
509
+ 'aws_kendra_data_source': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Kendra'),
510
+
511
+ # Personalize
512
+ 'aws_personalize_dataset_group': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Personalize'),
513
+ 'aws_personalize_solution': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Personalize'),
514
+
515
+ # Forecast
516
+ 'aws_forecast_dataset_group': ('Arch_Artificial-Intelligence', 'Arch_Amazon-Forecast'),
517
+
518
+ # ==========================================================================
519
+ # IoT
520
+ # ==========================================================================
521
+ 'aws_iot_thing': ('Arch_Internet-of-Things', 'Arch_AWS-IoT-Core'),
522
+ 'aws_iot_thing_type': ('Arch_Internet-of-Things', 'Arch_AWS-IoT-Core'),
523
+ 'aws_iot_policy': ('Arch_Internet-of-Things', 'Arch_AWS-IoT-Core'),
524
+ 'aws_iot_certificate': ('Arch_Internet-of-Things', 'Arch_AWS-IoT-Core'),
525
+ 'aws_iot_topic_rule': ('Arch_Internet-of-Things', 'Arch_AWS-IoT-Core'),
526
+
527
+ 'aws_iot_analytics_channel': ('Arch_Internet-of-Things', 'Arch_AWS-IoT-Analytics'),
528
+ 'aws_iot_analytics_datastore': ('Arch_Internet-of-Things', 'Arch_AWS-IoT-Analytics'),
529
+ 'aws_iot_analytics_pipeline': ('Arch_Internet-of-Things', 'Arch_AWS-IoT-Analytics'),
530
+
531
+ 'aws_greengrass_group': ('Arch_Internet-of-Things', 'Arch_AWS-IoT-Greengrass'),
532
+ 'aws_greengrassv2_component_version': ('Arch_Internet-of-Things', 'Arch_AWS-IoT-Greengrass'),
533
+ 'aws_greengrassv2_deployment': ('Arch_Internet-of-Things', 'Arch_AWS-IoT-Greengrass'),
534
+
535
+ # ==========================================================================
536
+ # MEDIA SERVICES
537
+ # ==========================================================================
538
+ 'aws_media_convert_queue': ('Arch_Media-Services', 'Arch_AWS-Elemental-MediaConvert'),
539
+ 'aws_medialive_channel': ('Arch_Media-Services', 'Arch_AWS-Elemental-MediaLive'),
540
+ 'aws_mediapackage_channel': ('Arch_Media-Services', 'Arch_AWS-Elemental-MediaPackage'),
541
+ 'aws_mediastore_container': ('Arch_Media-Services', 'Arch_AWS-Elemental-MediaStore'),
542
+ 'aws_ivs_channel': ('Arch_Media-Services', 'Arch_Amazon-Interactive-Video-Service'),
543
+ 'aws_elastic_transcoder_pipeline': ('Arch_Media-Services', 'Arch_Amazon-Elastic-Transcoder'),
544
+
545
+ # ==========================================================================
546
+ # MIGRATION
547
+ # ==========================================================================
548
+ 'aws_dms_replication_instance': ('Arch_Migration-Modernization', 'Arch_AWS-Database-Migration-Service'),
549
+ 'aws_dms_endpoint': ('Arch_Migration-Modernization', 'Arch_AWS-Database-Migration-Service'),
550
+ 'aws_dms_replication_task': ('Arch_Migration-Modernization', 'Arch_AWS-Database-Migration-Service'),
551
+
552
+ 'aws_datasync_task': ('Arch_Migration-Modernization', 'Arch_AWS-DataSync'),
553
+ 'aws_datasync_location_s3': ('Arch_Migration-Modernization', 'Arch_AWS-DataSync'),
554
+
555
+ 'aws_transfer_server': ('Arch_Migration-Modernization', 'Arch_AWS-Transfer-Family'),
556
+ 'aws_transfer_user': ('Arch_Migration-Modernization', 'Arch_AWS-Transfer-Family'),
557
+
558
+ # ==========================================================================
559
+ # GAME TECH
560
+ # ==========================================================================
561
+ 'aws_gamelift_fleet': ('Arch_Games', 'Arch_Amazon-GameLift-Servers'),
562
+ 'aws_gamelift_game_session_queue': ('Arch_Games', 'Arch_Amazon-GameLift-Servers'),
563
+ }
564
+
565
+ # Group icons for architectural elements (VPC, subnets, etc.)
566
+ GROUP_ICONS: Dict[str, str] = {
567
+ 'vpc': 'Virtual-private-cloud-VPC_32',
568
+ 'public_subnet': 'Public-subnet_32',
569
+ 'private_subnet': 'Private-subnet_32',
570
+ 'region': 'Region_32',
571
+ 'aws_cloud': 'AWS-Cloud_32',
572
+ 'availability_zone': 'Region_32',
573
+ }
574
+
575
+ # Color scheme for different resource categories
576
+ CATEGORY_COLORS: Dict[str, str] = {
577
+ 'Arch_Compute': '#ED7100',
578
+ 'Arch_Containers': '#ED7100',
579
+ 'Arch_Storage': '#3F8624',
580
+ 'Arch_Database': '#3B48CC',
581
+ 'Arch_Networking-Content-Delivery': '#8C4FFF',
582
+ 'Arch_App-Integration': '#E7157B',
583
+ 'Arch_Security-Identity-Compliance': '#DD344C',
584
+ 'Arch_Management-Governance': '#E7157B',
585
+ 'Arch_Artificial-Intelligence': '#01A88D',
586
+ 'Arch_Analytics': '#8C4FFF',
587
+ 'Arch_Business-Applications': '#DD344C',
588
+ 'Arch_Cloud-Financial-Management': '#3F8624',
589
+ # Resource Icons categories
590
+ 'Res_Networking-Content-Delivery': '#8C4FFF',
591
+ 'Res_Compute': '#ED7100',
592
+ 'Res_Storage': '#3F8624',
593
+ 'Res_Database': '#3B48CC',
594
+ 'Res_Security-Identity-Compliance': '#DD344C',
595
+ }
596
+
597
+
598
+ class IconMapper:
599
+ """Maps Terraform resources to AWS icons."""
600
+
601
+ def __init__(self, icons_base_path: Optional[str] = None):
602
+ self.icons_base_path = Path(icons_base_path) if icons_base_path else None
603
+ self._icon_cache: Dict[str, str] = {}
604
+ self._resource_icons_path: Optional[Path] = None
605
+ self._architecture_icons_path: Optional[Path] = None
606
+ self._group_icons_path: Optional[Path] = None
607
+
608
+ if self.icons_base_path and self.icons_base_path.exists():
609
+ self._discover_icon_directories()
610
+
611
+ def _discover_icon_directories(self) -> None:
612
+ """Auto-discover AWS icon directory structure."""
613
+ if not self.icons_base_path:
614
+ return
615
+
616
+ # Find Resource-Icons directory (pattern: Resource-Icons_*)
617
+ resource_dirs = list(self.icons_base_path.glob("Resource-Icons_*"))
618
+ self._resource_icons_path = resource_dirs[0] if resource_dirs else None
619
+
620
+ # Find Architecture-Service-Icons directory
621
+ arch_dirs = list(self.icons_base_path.glob("Architecture-Service-Icons_*"))
622
+ self._architecture_icons_path = arch_dirs[0] if arch_dirs else None
623
+
624
+ # Find Architecture-Group-Icons directory
625
+ group_dirs = list(self.icons_base_path.glob("Architecture-Group-Icons_*"))
626
+ self._group_icons_path = group_dirs[0] if group_dirs else None
627
+
628
+ def get_icon_path(
629
+ self,
630
+ resource_type: str,
631
+ size: int = 48,
632
+ format: str = 'svg'
633
+ ) -> Optional[Path]:
634
+ """Get the file path for a resource's icon."""
635
+ if not self.icons_base_path or resource_type not in TERRAFORM_TO_ICON:
636
+ return None
637
+
638
+ category, icon_name = TERRAFORM_TO_ICON[resource_type]
639
+
640
+ # Determine which icon set to use based on category prefix
641
+ if category.startswith('Res_'):
642
+ # Resource Icons (flat structure)
643
+ if not self._resource_icons_path:
644
+ return None
645
+ resource_icons_dir = self._resource_icons_path
646
+ icon_path = resource_icons_dir / category / f"{icon_name}_{size}.{format}"
647
+ if icon_path.exists():
648
+ return icon_path
649
+ # Try without category subfolder
650
+ for subdir in resource_icons_dir.iterdir():
651
+ if subdir.is_dir():
652
+ test_path = subdir / f"{icon_name}_{size}.{format}"
653
+ if test_path.exists():
654
+ return test_path
655
+ else:
656
+ # Architecture-Service-Icons (has size subdirectories)
657
+ if not self._architecture_icons_path:
658
+ return None
659
+ service_icons_dir = self._architecture_icons_path
660
+ icon_path = service_icons_dir / category / str(size) / f"{icon_name}_{size}.{format}"
661
+
662
+ if icon_path.exists():
663
+ return icon_path
664
+
665
+ # Try without size subdirectory
666
+ icon_path = service_icons_dir / category / f"{icon_name}_{size}.{format}"
667
+ if icon_path.exists():
668
+ return icon_path
669
+
670
+ # Try different sizes
671
+ for alt_size in [64, 48, 32, 16]:
672
+ icon_path = service_icons_dir / category / str(alt_size) / f"{icon_name}_{alt_size}.{format}"
673
+ if icon_path.exists():
674
+ return icon_path
675
+
676
+ return None
677
+
678
+ def get_group_icon_path(
679
+ self,
680
+ group_type: str,
681
+ format: str = 'svg'
682
+ ) -> Optional[Path]:
683
+ """Get the file path for a group icon (VPC, subnet, etc.)."""
684
+ if not self._group_icons_path or group_type not in GROUP_ICONS:
685
+ return None
686
+
687
+ icon_name = GROUP_ICONS[group_type]
688
+ icon_path = self._group_icons_path / f"{icon_name}.{format}"
689
+
690
+ if icon_path.exists():
691
+ return icon_path
692
+
693
+ return None
694
+
695
+ def get_icon_svg(self, resource_type: str, size: int = 48) -> Optional[str]:
696
+ """Get the SVG content for a resource's icon."""
697
+ cache_key = f"{resource_type}_{size}"
698
+ if cache_key in self._icon_cache:
699
+ return self._icon_cache[cache_key]
700
+
701
+ icon_path = self.get_icon_path(resource_type, size, 'svg')
702
+ if not icon_path:
703
+ # Return fallback colored rectangle
704
+ svg_content = self._generate_fallback_icon(resource_type, size)
705
+ self._icon_cache[cache_key] = svg_content
706
+ return svg_content
707
+
708
+ try:
709
+ with open(icon_path, 'r', encoding='utf-8') as f:
710
+ svg_content = f.read()
711
+ self._icon_cache[cache_key] = svg_content
712
+ return svg_content
713
+ except Exception:
714
+ # Return fallback on read error
715
+ svg_content = self._generate_fallback_icon(resource_type, size)
716
+ self._icon_cache[cache_key] = svg_content
717
+ return svg_content
718
+
719
+ def _generate_fallback_icon(self, resource_type: str, size: int = 48) -> str:
720
+ """Generate a fallback colored rectangle SVG when no icon is available."""
721
+ color = self.get_category_color(resource_type)
722
+ display_name = self.get_display_name(resource_type)
723
+
724
+ # Get short label (first letters of words or abbreviation)
725
+ if len(display_name) <= 4:
726
+ label = display_name.upper()
727
+ else:
728
+ words = display_name.split()
729
+ if len(words) > 1:
730
+ label = ''.join(w[0] for w in words if w).upper()[:4]
731
+ else:
732
+ label = display_name[:3].upper()
733
+
734
+ return f'''<svg xmlns="http://www.w3.org/2000/svg" width="{size}" height="{size}" viewBox="0 0 {size} {size}">
735
+ <rect width="{size}" height="{size}" rx="4" fill="{color}" fill-opacity="0.15" stroke="{color}" stroke-width="2"/>
736
+ <text x="{size/2}" y="{size/2 + 4}" text-anchor="middle" font-family="Arial, sans-serif" font-size="{size/4}" font-weight="bold" fill="{color}">{label}</text>
737
+ </svg>'''
738
+
739
+ def get_icon_data_uri(self, resource_type: str, size: int = 48) -> Optional[str]:
740
+ """Get a data URI for embedding the icon in HTML/SVG."""
741
+ svg_content = self.get_icon_svg(resource_type, size)
742
+ if not svg_content:
743
+ return None
744
+
745
+ encoded = base64.b64encode(svg_content.encode('utf-8')).decode('utf-8')
746
+ return f"data:image/svg+xml;base64,{encoded}"
747
+
748
+ def get_category_color(self, resource_type: str) -> str:
749
+ """Get the category color for a resource type."""
750
+ if resource_type not in TERRAFORM_TO_ICON:
751
+ return '#666666'
752
+
753
+ category, _ = TERRAFORM_TO_ICON[resource_type]
754
+ return CATEGORY_COLORS.get(category, '#666666')
755
+
756
+ def get_display_name(self, resource_type: str) -> str:
757
+ """Get a human-readable display name for a resource type."""
758
+ if resource_type not in TERRAFORM_TO_ICON:
759
+ # Convert aws_resource_type to "Resource Type"
760
+ name = resource_type.replace('aws_', '').replace('_', ' ').title()
761
+ return name
762
+
763
+ _, icon_name = TERRAFORM_TO_ICON[resource_type]
764
+ # Extract service name from icon name
765
+ # "Arch_Amazon-Simple-Queue-Service" -> "SQS"
766
+ name = icon_name.replace('Arch_', '').replace('Amazon-', '').replace('AWS-', '')
767
+
768
+ # Common abbreviations
769
+ abbreviations = {
770
+ 'Simple-Queue-Service': 'SQS',
771
+ 'Simple-Notification-Service': 'SNS',
772
+ 'Simple-Storage-Service': 'S3',
773
+ 'Simple-Email-Service': 'SES',
774
+ 'Elastic-Container-Service': 'ECS',
775
+ 'Elastic-Container-Registry': 'ECR',
776
+ 'Elastic-Kubernetes-Service': 'EKS',
777
+ 'Elastic-Load-Balancing': 'ELB',
778
+ 'Elastic-Block-Store': 'EBS',
779
+ 'Key-Management-Service': 'KMS',
780
+ 'Identity-and-Access-Management': 'IAM',
781
+ 'Certificate-Manager': 'ACM',
782
+ 'Virtual-Private-Cloud': 'VPC',
783
+ 'Relational-Database-Service': 'RDS',
784
+ }
785
+
786
+ for full, abbr in abbreviations.items():
787
+ if full in name:
788
+ return abbr
789
+
790
+ return name.replace('-', ' ')
791
+
792
+
793
+ def get_supported_resources() -> list:
794
+ """Get list of all supported Terraform resource types."""
795
+ return list(TERRAFORM_TO_ICON.keys())