Created IAC reverse generator
This commit is contained in:
59
src/iac_reverse/generator/resource_merger.py
Normal file
59
src/iac_reverse/generator/resource_merger.py
Normal file
@@ -0,0 +1,59 @@
|
||||
"""Multi-provider resource merging with conflict resolution.
|
||||
|
||||
Merges resources from multiple scan profiles into a unified inventory,
|
||||
resolving naming conflicts by prefixing with the provider identifier.
|
||||
"""
|
||||
|
||||
from dataclasses import replace
|
||||
from collections import defaultdict
|
||||
|
||||
from iac_reverse.models import DiscoveredResource, ScanResult
|
||||
|
||||
|
||||
class ResourceMerger:
|
||||
"""Merges resources from multiple ScanResult objects into a unified list.
|
||||
|
||||
When resources from different providers share the same name, the merger
|
||||
resolves the conflict by prefixing each conflicting resource's name with
|
||||
its provider identifier (e.g., "kubernetes_nginx", "docker_swarm_nginx").
|
||||
|
||||
Provider-specific attributes are preserved unchanged.
|
||||
"""
|
||||
|
||||
def merge(self, scan_results: list[ScanResult]) -> list[DiscoveredResource]:
|
||||
"""Merge resources from multiple scan results into a unified list.
|
||||
|
||||
Args:
|
||||
scan_results: List of ScanResult objects, one per provider/scan profile.
|
||||
|
||||
Returns:
|
||||
A unified list of DiscoveredResource with naming conflicts resolved
|
||||
by prefixing conflicting names with the provider identifier.
|
||||
"""
|
||||
# Collect all resources from all scan results
|
||||
all_resources: list[DiscoveredResource] = []
|
||||
for result in scan_results:
|
||||
all_resources.extend(result.resources)
|
||||
|
||||
# Group resources by name to detect conflicts
|
||||
resources_by_name: dict[str, list[DiscoveredResource]] = defaultdict(list)
|
||||
for resource in all_resources:
|
||||
resources_by_name[resource.name].append(resource)
|
||||
|
||||
# Identify conflicting names: same name from different providers
|
||||
conflicting_names: set[str] = set()
|
||||
for name, resources in resources_by_name.items():
|
||||
providers = {r.provider for r in resources}
|
||||
if len(providers) > 1:
|
||||
conflicting_names.add(name)
|
||||
|
||||
# Build the merged list, resolving conflicts
|
||||
merged: list[DiscoveredResource] = []
|
||||
for resource in all_resources:
|
||||
if resource.name in conflicting_names:
|
||||
prefixed_name = f"{resource.provider.value}_{resource.name}"
|
||||
merged.append(replace(resource, name=prefixed_name))
|
||||
else:
|
||||
merged.append(resource)
|
||||
|
||||
return merged
|
||||
Reference in New Issue
Block a user