diff --git a/doc/source/articles/policy_enf_dev.rst b/doc/source/articles/policy_enf_dev.rst index db0aff91..07843599 100644 --- a/doc/source/articles/policy_enf_dev.rst +++ b/doc/source/articles/policy_enf_dev.rst @@ -33,10 +33,10 @@ Value of property ``type`` is used as ``type_name`` parameter: Transformed to these rules: -- ``murano:objects+("83bff5ac", "83bff5ac", "io.murano.Environment")`` +- ``murano:objects+("83bff5ac", "tenant_id", "io.murano.Environment")`` - ``murano:objects+("83bff5ac", "e7a13d3c", "io.murano.databases.MySql")`` -.. note:: In case of rule for environment ``environment_id``, ``object_id`` are the same. +.. note:: The owner of the environment is a tenant ``murano:properties(object_id, property_name, property_value)`` @@ -84,10 +84,6 @@ Transformed to these rules: - ``murano:properties+("be3c5155", "networks.customNetworks", "10.0.1.0")`` - ``murano:properties+("be3c5155", "networks.customNetworks", "10.0.2.0")`` -There is one special property on environment for tenant_id: - -- ``murano:properties+("...", "tenant_id", "123")`` - ``murano:relationships(source, target, name)`` """""""""""""""""""""""""""""""""""""""""""""" @@ -127,6 +123,11 @@ Transformed to this rule: - ``murano:relationships+("0aafd67e", "ed8df2b0", "instance")`` +There are special relationships "services" from the environment to its applications: + +- ``murano:relationships+("env_id", "app_id", "services")`` + + ``murano:parent_types(object_id, parent_name)`` """"""""""""""""""""""""""""""""""""""""""""""" diff --git a/murano/policy/congress_rules.py b/murano/policy/congress_rules.py index 25103afc..3fbe8128 100644 --- a/murano/policy/congress_rules.py +++ b/murano/policy/congress_rules.py @@ -35,18 +35,11 @@ class CongressRulesManager(object): return self._rules self._env_id = model['?']['id'] - # Environment owner is tenant. - self._owner_id = tenant_id - - # Arbitrary property for tenant_id. - if tenant_id is not None: - r = PropertyRule(self._env_id, 'tenant_id', tenant_id) - self._rules.append(r) state_rule = StateRule(self._env_id, 'pending') self._rules.append(state_rule) - self._walk(model, self._process_item) + self._walk(model, owner_id=tenant_id) # Convert MuranoProperty containing reference to another object # to MuranoRelationship. @@ -91,33 +84,42 @@ class CongressRulesManager(object): return closure closure = closure_until_now - def _walk(self, obj, func): + def _walk(self, obj, owner_id, path=()): if obj is None: return obj = self._to_dict(obj) - func(obj) + new_owner = self._process_item(obj, owner_id, path) or owner_id if isinstance(obj, list): for v in obj: - self._walk(v, func) + self._walk(v, new_owner, path) elif isinstance(obj, dict): for key, value in obj.iteritems(): - self._walk(value, func) + self._walk(value, new_owner, path + (key, )) - def _process_item(self, obj): + def _process_item(self, obj, owner_id, path): if isinstance(obj, dict) and '?' in obj: - obj2 = self._create_object_rule(obj) - # Owner of components in environment is environment itself. - self._owner_id = self._env_id + obj_rule = self._create_object_rule(obj, owner_id) - self._rules.append(obj2) - self._rules.extend(self._create_propety_rules(obj2.obj_id, obj)) + self._rules.append(obj_rule) + # the environment has 'services' relationships + # to all its top-level applications + # traversal path is used to test whether + # we are at the right place within the tree + if path == ('applications',): + self._rules.append(RelationshipRule(self._env_id, + obj_rule.obj_id, + "services")) + self._rules.extend( + self._create_propety_rules(obj_rule.obj_id, obj)) cls = obj['?']['type'] types = self._get_parent_types(cls, self._class_loader) self._rules.extend(self._create_parent_type_rules(obj['?']['id'], types)) + # current object will be the owner for its subtree + return obj_rule.obj_id @staticmethod def _to_dict(obj): @@ -127,8 +129,8 @@ class CongressRulesManager(object): else: return obj - def _create_object_rule(self, app): - return ObjectRule(app['?']['id'], self._owner_id, app['?']['type']) + def _create_object_rule(self, app, owner_id): + return ObjectRule(app['?']['id'], owner_id, app['?']['type']) def _create_propety_rules(self, obj_id, obj, prefix=""): rules = [] diff --git a/murano/tests/functional/engine/test_policy_enf.py b/murano/tests/functional/engine/test_policy_enf.py index 67e62a89..6065e01e 100644 --- a/murano/tests/functional/engine/test_policy_enf.py +++ b/murano/tests/functional/engine/test_policy_enf.py @@ -24,14 +24,19 @@ import murano.tests.functional.common.tempest_utils as tempest_utils import murano.tests.functional.common.utils as common_utils CONGRESS_RULES = ['invalid_flavor_name("really.bad.flavor")', + 'murano_env_of_object(oid,eid):-' + 'murano:connected(eid,oid),' + 'murano:objects(eid,tid,"io.murano.Environment")', 'predeploy_errors(eid, obj_id, msg):-' - 'murano:objects(obj_id, eid, type),' + 'murano:objects(obj_id, pid, type),' + 'murano_env_of_object(obj_id, eid),' 'murano:properties(obj_id, "flavor", flavor_name),' 'invalid_flavor_name(flavor_name),' 'murano:properties(obj_id, "name", obj_name),' 'concat(obj_name, ": bad flavor", msg)', 'predeploy_errors(eid, obj_id, msg):-' - 'murano:objects(obj_id, eid, type),' + 'murano:objects(obj_id, pid, type),' + 'murano_env_of_object(obj_id, eid),' 'murano:properties(obj_id, "keyname", key_name),' 'missing_key(key_name),' 'murano:properties(obj_id, "name", obj_name),' diff --git a/murano/tests/unit/policy/expected_rules_model.txt b/murano/tests/unit/policy/expected_rules_model.txt index a138ddcc..7d2e4261 100644 --- a/murano/tests/unit/policy/expected_rules_model.txt +++ b/murano/tests/unit/policy/expected_rules_model.txt @@ -1,4 +1,4 @@ murano:objects+("0c810278-7282-4e4a-9d69-7b4c36b6ce6f", "c86104748a0c4907b4c5981e6d3bce9f", "io.murano.apps.linux.Git") murano:properties+("0c810278-7282-4e4a-9d69-7b4c36b6ce6f", "name", "git1") -murano:objects+("b840b71e-1805-46c5-9e6f-5a3d2c8d773e", "c86104748a0c4907b4c5981e6d3bce9f", "io.murano.resources.LinuxMuranoInstance") +murano:objects+("b840b71e-1805-46c5-9e6f-5a3d2c8d773e", "0c810278-7282-4e4a-9d69-7b4c36b6ce6f", "io.murano.resources.LinuxMuranoInstance") murano:properties+("b840b71e-1805-46c5-9e6f-5a3d2c8d773e", "name", "whjiyi3uzhxes6") \ No newline at end of file diff --git a/murano/tests/unit/policy/expected_rules_model_renamed.txt b/murano/tests/unit/policy/expected_rules_model_renamed.txt index a138ddcc..7d2e4261 100644 --- a/murano/tests/unit/policy/expected_rules_model_renamed.txt +++ b/murano/tests/unit/policy/expected_rules_model_renamed.txt @@ -1,4 +1,4 @@ murano:objects+("0c810278-7282-4e4a-9d69-7b4c36b6ce6f", "c86104748a0c4907b4c5981e6d3bce9f", "io.murano.apps.linux.Git") murano:properties+("0c810278-7282-4e4a-9d69-7b4c36b6ce6f", "name", "git1") -murano:objects+("b840b71e-1805-46c5-9e6f-5a3d2c8d773e", "c86104748a0c4907b4c5981e6d3bce9f", "io.murano.resources.LinuxMuranoInstance") +murano:objects+("b840b71e-1805-46c5-9e6f-5a3d2c8d773e", "0c810278-7282-4e4a-9d69-7b4c36b6ce6f", "io.murano.resources.LinuxMuranoInstance") murano:properties+("b840b71e-1805-46c5-9e6f-5a3d2c8d773e", "name", "whjiyi3uzhxes6") \ No newline at end of file diff --git a/murano/tests/unit/policy/expected_rules_wordpress.txt b/murano/tests/unit/policy/expected_rules_wordpress.txt index 142a6e1a..19bb8f54 100644 --- a/murano/tests/unit/policy/expected_rules_wordpress.txt +++ b/murano/tests/unit/policy/expected_rules_wordpress.txt @@ -16,7 +16,7 @@ murano:properties+("e7a13d3c-b3c9-42fa-975d-a47b142fd233", "password", "Adminadm murano:parent_types+("e7a13d3c-b3c9-42fa-975d-a47b142fd233", "io.murano.databases.SqlDatabase") murano:parent_types+("e7a13d3c-b3c9-42fa-975d-a47b142fd233", "io.murano.Object") murano:parent_types+("e7a13d3c-b3c9-42fa-975d-a47b142fd233", "io.murano.Application") -murano:objects+("825dc61d-217a-4fd8-80fc-43807f8d6fa2", "83bff5acf8354816b08cf9b4917c898d", "io.murano.resources.LinuxMuranoInstance") +murano:objects+("825dc61d-217a-4fd8-80fc-43807f8d6fa2", "e7a13d3c-b3c9-42fa-975d-a47b142fd233", "io.murano.resources.LinuxMuranoInstance") murano:properties+("825dc61d-217a-4fd8-80fc-43807f8d6fa2", "name", "qgijhi4uwe5wd8") murano:properties+("825dc61d-217a-4fd8-80fc-43807f8d6fa2", "assignFloatingIp", "False") murano:properties+("825dc61d-217a-4fd8-80fc-43807f8d6fa2", "networks.useFlatNetwork", "False") @@ -31,7 +31,7 @@ murano:properties+("d224db7d-081d-47a4-9333-9d2677b90b1f", "name", "ApacheHttpSe murano:properties+("d224db7d-081d-47a4-9333-9d2677b90b1f", "enablePHP", "True") murano:parent_types+("d224db7d-081d-47a4-9333-9d2677b90b1f", "io.murano.Object") murano:parent_types+("d224db7d-081d-47a4-9333-9d2677b90b1f", "io.murano.Application") -murano:objects+("3ddd4945-e4b8-4dac-9f85-537fc0957151", "83bff5acf8354816b08cf9b4917c898d", "io.murano.resources.LinuxMuranoInstance") +murano:objects+("3ddd4945-e4b8-4dac-9f85-537fc0957151", "d224db7d-081d-47a4-9333-9d2677b90b1f", "io.murano.resources.LinuxMuranoInstance") murano:properties+("3ddd4945-e4b8-4dac-9f85-537fc0957151", "name", "yeqsbi4uwejfg7") murano:properties+("3ddd4945-e4b8-4dac-9f85-537fc0957151", "assignFloatingIp", "False") murano:properties+("3ddd4945-e4b8-4dac-9f85-537fc0957151", "networks.useFlatNetwork", "False") @@ -48,7 +48,7 @@ murano:properties+("33e91790-5c44-40ce-9292-9dd4856325a0", "database", "zabbix") murano:properties+("33e91790-5c44-40ce-9292-9dd4856325a0", "password", "Adminadmin#1") murano:parent_types+("33e91790-5c44-40ce-9292-9dd4856325a0", "io.murano.Object") murano:parent_types+("33e91790-5c44-40ce-9292-9dd4856325a0", "io.murano.Application") -murano:objects+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "83bff5acf8354816b08cf9b4917c898d", "io.murano.resources.LinuxMuranoInstance") +murano:objects+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "33e91790-5c44-40ce-9292-9dd4856325a0", "io.murano.resources.LinuxMuranoInstance") murano:properties+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "name", "gzxgdi4uwfjt57") murano:properties+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "assignFloatingIp", "False") murano:properties+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "networks.useFlatNetwork", "False") @@ -71,7 +71,7 @@ murano:properties+("33e91790-5c44-40ce-9292-9dd4856325a0", "database", "zabbix") murano:properties+("33e91790-5c44-40ce-9292-9dd4856325a0", "password", "Adminadmin#1") murano:parent_types+("33e91790-5c44-40ce-9292-9dd4856325a0", "io.murano.Object") murano:parent_types+("33e91790-5c44-40ce-9292-9dd4856325a0", "io.murano.Application") -murano:objects+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "83bff5acf8354816b08cf9b4917c898d", "io.murano.resources.LinuxMuranoInstance") +murano:objects+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "33e91790-5c44-40ce-9292-9dd4856325a0", "io.murano.resources.LinuxMuranoInstance") murano:properties+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "name", "gzxgdi4uwfjt57") murano:properties+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "assignFloatingIp", "False") murano:properties+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "networks.useFlatNetwork", "False") @@ -101,7 +101,7 @@ murano:properties+("33e91790-5c44-40ce-9292-9dd4856325a0", "database", "zabbix") murano:properties+("33e91790-5c44-40ce-9292-9dd4856325a0", "password", "Adminadmin#1") murano:parent_types+("33e91790-5c44-40ce-9292-9dd4856325a0", "io.murano.Object") murano:parent_types+("33e91790-5c44-40ce-9292-9dd4856325a0", "io.murano.Application") -murano:objects+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "83bff5acf8354816b08cf9b4917c898d", "io.murano.resources.LinuxMuranoInstance") +murano:objects+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "33e91790-5c44-40ce-9292-9dd4856325a0", "io.murano.resources.LinuxMuranoInstance") murano:properties+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "name", "gzxgdi4uwfjt57") murano:properties+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "assignFloatingIp", "False") murano:properties+("0b568a74-66c9-4e73-84d8-7dd1b96066ec", "networks.useFlatNetwork", "False") @@ -119,7 +119,7 @@ murano:properties+("e7a13d3c-b3c9-42fa-975d-a47b142fd233", "password", "Adminadm murano:parent_types+("e7a13d3c-b3c9-42fa-975d-a47b142fd233", "io.murano.databases.SqlDatabase") murano:parent_types+("e7a13d3c-b3c9-42fa-975d-a47b142fd233", "io.murano.Object") murano:parent_types+("e7a13d3c-b3c9-42fa-975d-a47b142fd233", "io.murano.Application") -murano:objects+("825dc61d-217a-4fd8-80fc-43807f8d6fa2", "83bff5acf8354816b08cf9b4917c898d", "io.murano.resources.LinuxMuranoInstance") +murano:objects+("825dc61d-217a-4fd8-80fc-43807f8d6fa2", "e7a13d3c-b3c9-42fa-975d-a47b142fd233", "io.murano.resources.LinuxMuranoInstance") murano:properties+("825dc61d-217a-4fd8-80fc-43807f8d6fa2", "name", "qgijhi4uwe5wd8") murano:properties+("825dc61d-217a-4fd8-80fc-43807f8d6fa2", "assignFloatingIp", "False") murano:properties+("825dc61d-217a-4fd8-80fc-43807f8d6fa2", "networks.useFlatNetwork", "False") @@ -134,7 +134,7 @@ murano:properties+("d224db7d-081d-47a4-9333-9d2677b90b1f", "name", "ApacheHttpSe murano:properties+("d224db7d-081d-47a4-9333-9d2677b90b1f", "enablePHP", "True") murano:parent_types+("d224db7d-081d-47a4-9333-9d2677b90b1f", "io.murano.Object") murano:parent_types+("d224db7d-081d-47a4-9333-9d2677b90b1f", "io.murano.Application") -murano:objects+("3ddd4945-e4b8-4dac-9f85-537fc0957151", "83bff5acf8354816b08cf9b4917c898d", "io.murano.resources.LinuxMuranoInstance") +murano:objects+("3ddd4945-e4b8-4dac-9f85-537fc0957151", "d224db7d-081d-47a4-9333-9d2677b90b1f", "io.murano.resources.LinuxMuranoInstance") murano:properties+("3ddd4945-e4b8-4dac-9f85-537fc0957151", "name", "yeqsbi4uwejfg7") murano:properties+("3ddd4945-e4b8-4dac-9f85-537fc0957151", "assignFloatingIp", "False") murano:properties+("3ddd4945-e4b8-4dac-9f85-537fc0957151", "networks.useFlatNetwork", "False") diff --git a/murano/tests/unit/policy/test_congress_rules.py b/murano/tests/unit/policy/test_congress_rules.py index 2b664552..c218762d 100644 --- a/murano/tests/unit/policy/test_congress_rules.py +++ b/murano/tests/unit/policy/test_congress_rules.py @@ -118,6 +118,17 @@ class TestCongressRules(unittest.TestCase): 'murano:connected+("8ce94f23-f16a-40a1-9d9d-a877266c315d", ' '"fc6b8c41-166f-4fc9-a640-d82009e0a03d")' in rules_str) + def test_convert_model_services_relationship(self): + rules_str = self._create_rules_str('model_with_relations.yaml') + + self.assertTrue( + 'murano:relationships+("3409bdd0590e4c60b70fda5e6777ff96", ' + '"8ce94f23-f16a-40a1-9d9d-a877266c315d", "services")' in rules_str) + + self.assertTrue( + 'murano:relationships+("3409bdd0590e4c60b70fda5e6777ff96", ' + '"50fa68ff-cd9a-4845-b573-2c80879d158d", "services")' in rules_str) + def test_convert_model_complex(self): self._create_and_check_rules_str('model_complex') @@ -189,16 +200,15 @@ class TestCongressRules(unittest.TestCase): self.assertTrue('murano:objects+("1", "{0}", "t1")'.format(tenant_id) in rules_str) self.assertTrue('murano:objects+("2", "1", "t2")' in rules_str) - self.assertTrue('murano:objects+("3", "1", "t3")' in rules_str) + self.assertTrue('murano:objects+("3", "2", "t3")' in rules_str) - def test_tenant_id(self): + def test_environment_owner(self): model = self._load_file("model.yaml") congress_rules = congress.CongressRulesManager() rules = congress_rules.convert(model, tenant_id='tenant1') rules_str = ", \n".join(map(str, rules)) - self.assertTrue( - 'murano:properties+("c86104748a0c4907b4c5981e6d3bce9f", ' - '"tenant_id", "tenant1")' in rules_str) + self.assertTrue('murano:objects+("c86104748a0c4907b4c5981e6d3bce9f", ' + '"tenant1", "io.murano.Environment")' in rules_str) def test_wordpress(self): class_loader = MockClassLoader([