diff --git a/v2/ansible/playbook/role.py b/v2/ansible/playbook/role.py index 38a8ac195d0..b4b7eed012a 100644 --- a/v2/ansible/playbook/role.py +++ b/v2/ansible/playbook/role.py @@ -41,6 +41,7 @@ __all__ = ['Role'] # will be based on the repr() of the dictionary object) _ROLE_CACHE = dict() +# The valid metadata keys for meta/main.yml files _VALID_METADATA_KEYS = [ 'dependencies', 'allow_duplicates', @@ -369,20 +370,30 @@ class Role(Base): if parent_role not in self._parents: self._parents.append(parent_role) - def get_variables(self): - # returns the merged variables for this role, including - # recursively merging those of all child roles - return dict() + def get_parents(self): + return self._parents - def get_immediate_dependencies(self): - return self._dependencies + # FIXME: not yet used + #def get_variables(self): + # # returns the merged variables for this role, including + # # recursively merging those of all child roles + # return dict() + + def get_direct_dependencies(self): + return self._attributes['dependencies'][:] def get_all_dependencies(self): # returns a list built recursively, of all deps from # all child dependencies - all_deps = [] - for dep in self._dependencies: - list_union(all_deps, dep.get_all_dependencies()) - all_deps = list_union(all_deps, self.dependencies) - return all_deps + + child_deps = [] + direct_deps = self.get_direct_dependencies() + + for dep in direct_deps: + dep_deps = dep.get_all_dependencies() + for dep_dep in dep_deps: + if dep_dep not in child_deps: + child_deps.append(dep_dep) + + return direct_deps + child_deps diff --git a/v2/test/playbook/test_role.py b/v2/test/playbook/test_role.py index 094c5c3f494..2c1ca6c959d 100644 --- a/v2/test/playbook/test_role.py +++ b/v2/test/playbook/test_role.py @@ -22,7 +22,7 @@ __metaclass__ = type from ansible.compat.tests import unittest from ansible.compat.tests.mock import patch, MagicMock -from ansible.errors import AnsibleParserError +from ansible.errors import AnsibleError, AnsibleParserError from ansible.playbook.block import Block from ansible.playbook.role import Role from ansible.playbook.task import Task @@ -124,16 +124,30 @@ class TestRole(unittest.TestCase): return ('foo', '/etc/ansible/roles/foo') elif role == 'bar': return ('bar', '/etc/ansible/roles/bar') + elif role == 'baz': + return ('baz', '/etc/ansible/roles/baz') + elif role == 'bam': + return ('bam', '/etc/ansible/roles/bam') elif role == 'bad1': return ('bad1', '/etc/ansible/roles/bad1') elif role == 'bad2': return ('bad2', '/etc/ansible/roles/bad2') + elif role == 'recursive1': + return ('recursive1', '/etc/ansible/roles/recursive1') + elif role == 'recursive2': + return ('recursive2', '/etc/ansible/roles/recursive2') def fake_load_role_yaml(role_path, subdir): if role_path == '/etc/ansible/roles/foo': if subdir == 'meta': return dict(dependencies=['bar'], allow_duplicates=True, galaxy_info=dict(a='1', b='2', c='3')) elif role_path == '/etc/ansible/roles/bar': + if subdir == 'meta': + return dict(dependencies=['baz']) + elif role_path == '/etc/ansible/roles/baz': + if subdir == 'meta': + return dict(dependencies=['bam']) + elif role_path == '/etc/ansible/roles/bam': if subdir == 'meta': return dict() elif role_path == '/etc/ansible/roles/bad1': @@ -142,21 +156,36 @@ class TestRole(unittest.TestCase): elif role_path == '/etc/ansible/roles/bad2': if subdir == 'meta': return dict(foo='bar') + elif role_path == '/etc/ansible/roles/recursive1': + if subdir == 'meta': + return dict(dependencies=['recursive2']) + elif role_path == '/etc/ansible/roles/recursive2': + if subdir == 'meta': + return dict(dependencies=['recursive1']) return None _get_role_path.side_effect = fake_get_role_path _load_role_yaml.side_effect = fake_load_role_yaml r = Role.load('foo') - self.assertEqual(len(r.dependencies), 1) - self.assertEqual(type(r.dependencies[0]), Role) - self.assertEqual(len(r.dependencies[0]._parents), 1) - self.assertEqual(r.dependencies[0]._parents[0], r) + role_deps = r.get_direct_dependencies() + + self.assertEqual(len(role_deps), 1) + self.assertEqual(type(role_deps[0]), Role) + self.assertEqual(len(role_deps[0].get_parents()), 1) + self.assertEqual(role_deps[0].get_parents()[0], r) self.assertEqual(r.allow_duplicates, True) self.assertEqual(r.galaxy_info, dict(a='1', b='2', c='3')) + all_deps = r.get_all_dependencies() + self.assertEqual(len(all_deps), 3) + self.assertEqual(all_deps[0].role_name, 'bar') + self.assertEqual(all_deps[1].role_name, 'baz') + self.assertEqual(all_deps[2].role_name, 'bam') + self.assertRaises(AnsibleParserError, Role.load, 'bad1') self.assertRaises(AnsibleParserError, Role.load, 'bad2') + self.assertRaises(AnsibleError, Role.load, 'recursive1') @patch.object(Role, '_get_role_path') @patch.object(Role, '_load_role_yaml') @@ -174,4 +203,6 @@ class TestRole(unittest.TestCase): r = Role.load(dict(role='foo')) + # FIXME: add tests for the more complex url-type + # constructions and tags/when statements