forked from ungleich-public/cdist
prevent requirements from leaking into autorequired objects and creating circular references
Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch> Conflicts: cdist/test/autorequire/__init__.py
This commit is contained in:
parent
cb829ec8d0
commit
06fb7491fa
4 changed files with 23 additions and 7 deletions
|
@ -23,6 +23,7 @@ import logging
|
|||
import os
|
||||
import itertools
|
||||
import fnmatch
|
||||
import pprint
|
||||
|
||||
import cdist
|
||||
|
||||
|
@ -77,14 +78,15 @@ class DependencyResolver(object):
|
|||
lists of all dependencies including the key object itself.
|
||||
"""
|
||||
if self._dependencies is None:
|
||||
log.info("Resolving dependencies...")
|
||||
self._dependencies = d = {}
|
||||
self.log.info("Resolving dependencies...")
|
||||
self._dependencies = {}
|
||||
self._preprocess_requirements()
|
||||
for name,cdist_object in self.objects.items():
|
||||
resolved = []
|
||||
unresolved = []
|
||||
self._resolve_object_dependencies(cdist_object, resolved, unresolved)
|
||||
d[name] = resolved
|
||||
self._dependencies[name] = resolved
|
||||
self.log.debug(self._dependencies)
|
||||
return self._dependencies
|
||||
|
||||
def find_requirements_by_name(self, requirements):
|
||||
|
@ -120,9 +122,12 @@ class DependencyResolver(object):
|
|||
# that the parent has so that user defined requirements are
|
||||
# fullfilled and processed in the expected order.
|
||||
for auto_requirement in self.find_requirements_by_name(cdist_object.autorequire):
|
||||
for requirement in cdist_object.requirements:
|
||||
if requirement not in auto_requirement.requirements:
|
||||
auto_requirement.requirements.append(requirement)
|
||||
for requirement in self.find_requirements_by_name(cdist_object.requirements):
|
||||
requirement_object_all_requirements = list(requirement.requirements) + list(requirement.autorequire)
|
||||
if (requirement.name not in auto_requirement.requirements
|
||||
and auto_requirement.name not in requirement_object_all_requirements):
|
||||
self.log.debug('Adding %s to %s.requirements', requirement.name, auto_requirement)
|
||||
auto_requirement.requirements.append(requirement.name)
|
||||
# On the other hand the parent shall depend on all the children
|
||||
# it created so that the user can setup dependencies on it as a
|
||||
# whole without having to know anything about the parents
|
||||
|
@ -149,7 +154,9 @@ class DependencyResolver(object):
|
|||
self.log.debug("Object %s requires %s", cdist_object, required_object)
|
||||
if required_object not in resolved:
|
||||
if required_object in unresolved:
|
||||
raise CircularReferenceError(cdist_object, required_object)
|
||||
error = CircularReferenceError(cdist_object, required_object)
|
||||
self.log.error('%s: %s', error, pprint.pformat(self._dependencies))
|
||||
raise error
|
||||
self._resolve_object_dependencies(required_object, resolved, unresolved)
|
||||
resolved.append(cdist_object)
|
||||
unresolved.remove(cdist_object)
|
||||
|
|
|
@ -83,3 +83,9 @@ class AutorequireTestCase(test.CdistTestCase):
|
|||
self.config.stage_prepare()
|
||||
# raises CircularDependecyError
|
||||
self.config.stage_run()
|
||||
|
||||
def test_recursive_type(self):
|
||||
self.context.initial_manifest = os.path.join(self.config.local.manifest_path, 'recursive_type')
|
||||
self.config.stage_prepare()
|
||||
# raises CircularDependecyError
|
||||
self.config.stage_run()
|
||||
|
|
2
cdist/test/autorequire/fixtures/conf/manifest/recursive_type
Executable file
2
cdist/test/autorequire/fixtures/conf/manifest/recursive_type
Executable file
|
@ -0,0 +1,2 @@
|
|||
__git foo
|
||||
require="__git/foo" __git bar
|
1
cdist/test/autorequire/fixtures/conf/type/__git/manifest
Normal file
1
cdist/test/autorequire/fixtures/conf/type/__git/manifest
Normal file
|
@ -0,0 +1 @@
|
|||
__package git
|
Loading…
Reference in a new issue