Skip to content

Commit

Permalink
[BLAZ-733] Componentes duplicated when multiple parents (#408)
Browse files Browse the repository at this point in the history
Co-authored-by: Santi Manero <100587318+smaneroiriusrisk@users.noreply.github.com>
  • Loading branch information
jmgarcia-iriusrisk and smaneroiriusrisk authored Oct 31, 2024
1 parent 6d864a6 commit 3e906c2
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 17 deletions.
4 changes: 2 additions & 2 deletions slp_tfplan/slp_tfplan/graph/relationships_extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import networkx as nx
from networkx import DiGraph

from slp_tfplan.slp_tfplan.objects.tfplan_objects import TFPlanComponent
from slp_tfplan.slp_tfplan.load.tfplan_to_resource_dict import remove_name_prefix
from slp_tfplan.slp_tfplan.objects.tfplan_objects import TFPlanComponent

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -33,7 +33,7 @@ def get_closest_resources(self, source_component: TFPlanComponent, target_candid
if not linked_resources or path_size < min_size:
min_size = path_size
linked_resources = [target_candidate.id]
elif path_size == min_size:
elif path_size == min_size and target_candidate.id not in linked_resources:
linked_resources.append(target_candidate.id)

return linked_resources
Expand Down
2 changes: 1 addition & 1 deletion slp_tfplan/slp_tfplan/transformers/children_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ def _calculate_component_parents(self, component: TFPlanComponent) -> [str]:

return self._find_parent_by_closest_relationship(
component,
self._get_parent_candidates(PARENTS_TYPES_BY_CHILDREN_TYPE[component.tf_type]))
self._find_components_by_type(PARENTS_TYPES_BY_CHILDREN_TYPE[component.tf_type]))
12 changes: 6 additions & 6 deletions slp_tfplan/slp_tfplan/transformers/hierarchy_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def set_component_parent(component: TFPlanComponent, parent_id: str):
component.parent = parent_id


def _find_parent_candidates_by_type(components: [], parent_type: str) -> []:
def _find_components_by_type(components: [], parent_type: str) -> []:
return list(filter(lambda c: __extract_type(c.id) == parent_type, components))


Expand Down Expand Up @@ -79,10 +79,10 @@ def _calculate_component_parents(self, component: TFPlanComponent) -> [str]:
def _find_parent_by_closest_relationship(self, component: TFPlanComponent, parent_candidates: []):
return self.relationships_extractor.get_closest_resources(component, parent_candidates)

def _get_parent_candidates(self, parent_types: []):
parent_candidates = []
def _find_components_by_type(self, _types: []):
components = []

for parent_type in parent_types:
parent_candidates.extend(_find_parent_candidates_by_type(self.otm.components, parent_type))
for _type in _types:
components.extend(_find_components_by_type(self.otm.components, _type))

return parent_candidates
return components
14 changes: 8 additions & 6 deletions slp_tfplan/slp_tfplan/transformers/parent_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@
from slp_tfplan.slp_tfplan.objects.tfplan_objects import TFPlanComponent, TFPlanOTM
from slp_tfplan.slp_tfplan.transformers.hierarchy_calculator import HierarchyCalculator

PARENT_TYPES = ['aws_subnet', 'aws_vpc', 'azurerm_subnet', 'azurerm_virtual_network']

PARENT_TYPES = {
'subnets': ['aws_subnet', 'azurerm_subnet'],
'vpcs': ['aws_vpc', 'azurerm_virtual_network']
}

class ParentCalculator(HierarchyCalculator):

def __init__(self, otm: TFPlanOTM, graph: DiGraph):
super().__init__(otm, graph)
self.parent_candidates = self._get_parent_candidates(PARENT_TYPES)
self.subnet_candidates = self._find_components_by_type(PARENT_TYPES['subnets'])
self.vpc_candidates = self._find_components_by_type(PARENT_TYPES['vpcs'])

def _calculate_component_parents(self, component: TFPlanComponent) -> [str]:
return self._find_parent_by_closest_relationship(component, self.parent_candidates)


return self._find_parent_by_closest_relationship(component, self.subnet_candidates) or \
self._find_parent_by_closest_relationship(component, self.vpc_candidates)
48 changes: 46 additions & 2 deletions slp_tfplan/tests/unit/transformers/test_parent_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def test_two_straight_paths_different_lengths(self):
# AND the parent are calculated according the relationships among components
assert_parents(otm.components, {child_component_id: parent_component_id})

def test_two_straight_paths_same_lengths(self):
def test_two_straight_paths_same_length_to_subnets(self):
# GIVEN an OTM dict with two components and a default trustZone
child_component = build_mocked_component({
'component_name': 'child',
Expand All @@ -183,7 +183,7 @@ def test_two_straight_paths_same_lengths(self):

parent_component_2 = build_mocked_component({
'component_name': 'parent_2',
'tf_type': PARENT_TYPES[1],
'tf_type': PARENT_TYPES[0],
})
parent_component_2_id = parent_component_2.id

Expand All @@ -210,3 +210,47 @@ def test_two_straight_paths_same_lengths(self):
f'{child_component_id}_0': parent_component_1_id,
f'{child_component_id}_1': parent_component_2_id,
})

def test_two_straight_paths_same_length_to_subnet_and_network(self):
# GIVEN an OTM dict with two components and a default trustZone
child_component = build_mocked_component({
'component_name': 'child',
'tf_type': CHILD_TYPE,
})
child_component_id = child_component.id

subnet = build_mocked_component({
'component_name': 'subnet',
'tf_type': PARENT_TYPES[0],
})
subnet_id = subnet.id

network = build_mocked_component({
'component_name': 'network',
'tf_type': PARENT_TYPES[1],
})
network_id = network.id

otm = build_mocked_otm([child_component, subnet, network])

# AND a graph a two paths from the same child to two parents
graph = build_tfgraph([
(child_component.id, subnet.id),
(child_component.id, network.id),
(subnet.id, network.id),
(network.id, None)
])

# WHEN ParentCalculator::calculate_parents is invoked
ParentCalculator(otm=otm, graph=graph).transform()

# THEN the child component is not duplicated
assert len(otm.components) == 3

# AND the parent are calculated according the relationships among components
assert_parents(
components=otm.components,
relationships={
f'{child_component_id}': subnet_id,
f'{subnet_id}': network_id,
})

0 comments on commit 3e906c2

Please sign in to comment.