Merge "Computes transitive relationships in murano model"
This commit is contained in:
commit
bcb142cf7d
@ -56,8 +56,41 @@ class CongressRulesManager(object):
|
|||||||
self._rules = [self._create_relationship(rule, object_ids)
|
self._rules = [self._create_relationship(rule, object_ids)
|
||||||
for rule in self._rules]
|
for rule in self._rules]
|
||||||
|
|
||||||
|
relations = [(rel.source_id, rel.target_id)
|
||||||
|
for rel in self._rules
|
||||||
|
if isinstance(rel, RelationshipRule)]
|
||||||
|
closure = self.transitive_closure(relations)
|
||||||
|
|
||||||
|
for rel in closure:
|
||||||
|
self._rules.append(ConnectedRule(rel[0], rel[1]))
|
||||||
|
|
||||||
return self._rules
|
return self._rules
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def transitive_closure(relations):
|
||||||
|
"""Computes transitive closure on a directed graph.
|
||||||
|
|
||||||
|
In other words computes reachability within the graph.
|
||||||
|
E.g. {(1, 2), (2, 3)} -> {(1, 2), (2, 3), (1, 3)}
|
||||||
|
(1, 3) was added because there is path from 1 to 3 in the graph.
|
||||||
|
|
||||||
|
:param relations: list of relations/edges in form of tuples
|
||||||
|
:return: transitive closure including original relations
|
||||||
|
"""
|
||||||
|
closure = set(relations)
|
||||||
|
while True:
|
||||||
|
# Attempts to discover new transitive relations
|
||||||
|
# by joining 2 subsequent relations/edges within the graph.
|
||||||
|
new_relations = {(x, w) for x, y in closure
|
||||||
|
for q, w in closure if q == y}
|
||||||
|
# Creates union with already discovered relations.
|
||||||
|
closure_until_now = closure | new_relations
|
||||||
|
# If no new relations were discovered in last cycle
|
||||||
|
# the computation is finished.
|
||||||
|
if closure_until_now == closure:
|
||||||
|
return closure
|
||||||
|
closure = closure_until_now
|
||||||
|
|
||||||
def _walk(self, obj, func):
|
def _walk(self, obj, func):
|
||||||
|
|
||||||
if obj is None:
|
if obj is None:
|
||||||
@ -195,6 +228,16 @@ class RelationshipRule(object):
|
|||||||
self.source_id, self.target_id, self.rel_name)
|
self.source_id, self.target_id, self.rel_name)
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectedRule(object):
|
||||||
|
def __init__(self, source_id, target_id):
|
||||||
|
self.source_id = source_id
|
||||||
|
self.target_id = target_id
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return 'murano:connected+("{0}", "{1}")'.format(
|
||||||
|
self.source_id, self.target_id)
|
||||||
|
|
||||||
|
|
||||||
class ParentTypeRule(object):
|
class ParentTypeRule(object):
|
||||||
def __init__(self, obj_id, type_name):
|
def __init__(self, obj_id, type_name):
|
||||||
self.obj_id = obj_id
|
self.obj_id = obj_id
|
||||||
|
@ -71,6 +71,12 @@ class TestCongressRules(unittest.TestCase):
|
|||||||
|
|
||||||
return rules_str
|
return rules_str
|
||||||
|
|
||||||
|
def test_transitive_closure(self):
|
||||||
|
closure = congress.CongressRulesManager.transitive_closure(
|
||||||
|
[(1, 2), (2, 3), (3, 4)])
|
||||||
|
self.assertTrue((1, 4) in closure)
|
||||||
|
self.assertTrue((2, 4) in closure)
|
||||||
|
|
||||||
def test_empty_model(self):
|
def test_empty_model(self):
|
||||||
congress_rules = congress.CongressRulesManager()
|
congress_rules = congress.CongressRulesManager()
|
||||||
rules = congress_rules.convert(None)
|
rules = congress_rules.convert(None)
|
||||||
@ -101,6 +107,17 @@ class TestCongressRules(unittest.TestCase):
|
|||||||
'murano:relationships+("0aafd67e-72e9-4ae0-bb62-fe724f77df2a", '
|
'murano:relationships+("0aafd67e-72e9-4ae0-bb62-fe724f77df2a", '
|
||||||
'"ed8df2b0-ddd2-4009-b3c9-2e7a368f3cb8", "instance")' in rules_str)
|
'"ed8df2b0-ddd2-4009-b3c9-2e7a368f3cb8", "instance")' in rules_str)
|
||||||
|
|
||||||
|
def test_convert_model_transitive_relationships(self):
|
||||||
|
rules_str = self._create_rules_str('model_with_relations.yaml')
|
||||||
|
|
||||||
|
self.assertTrue(
|
||||||
|
'murano:connected+("50fa68ff-cd9a-4845-b573-2c80879d158d", '
|
||||||
|
'"8ce94f23-f16a-40a1-9d9d-a877266c315d")' in rules_str)
|
||||||
|
|
||||||
|
self.assertTrue(
|
||||||
|
'murano:connected+("8ce94f23-f16a-40a1-9d9d-a877266c315d", '
|
||||||
|
'"fc6b8c41-166f-4fc9-a640-d82009e0a03d")' in rules_str)
|
||||||
|
|
||||||
def test_convert_model_complex(self):
|
def test_convert_model_complex(self):
|
||||||
self._create_and_check_rules_str('model_complex')
|
self._create_and_check_rules_str('model_complex')
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user