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 os
|
||||||
import itertools
|
import itertools
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
import pprint
|
||||||
|
|
||||||
import cdist
|
import cdist
|
||||||
|
|
||||||
|
@ -77,14 +78,15 @@ class DependencyResolver(object):
|
||||||
lists of all dependencies including the key object itself.
|
lists of all dependencies including the key object itself.
|
||||||
"""
|
"""
|
||||||
if self._dependencies is None:
|
if self._dependencies is None:
|
||||||
log.info("Resolving dependencies...")
|
self.log.info("Resolving dependencies...")
|
||||||
self._dependencies = d = {}
|
self._dependencies = {}
|
||||||
self._preprocess_requirements()
|
self._preprocess_requirements()
|
||||||
for name,cdist_object in self.objects.items():
|
for name,cdist_object in self.objects.items():
|
||||||
resolved = []
|
resolved = []
|
||||||
unresolved = []
|
unresolved = []
|
||||||
self._resolve_object_dependencies(cdist_object, 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
|
return self._dependencies
|
||||||
|
|
||||||
def find_requirements_by_name(self, requirements):
|
def find_requirements_by_name(self, requirements):
|
||||||
|
@ -120,9 +122,12 @@ class DependencyResolver(object):
|
||||||
# that the parent has so that user defined requirements are
|
# that the parent has so that user defined requirements are
|
||||||
# fullfilled and processed in the expected order.
|
# fullfilled and processed in the expected order.
|
||||||
for auto_requirement in self.find_requirements_by_name(cdist_object.autorequire):
|
for auto_requirement in self.find_requirements_by_name(cdist_object.autorequire):
|
||||||
for requirement in cdist_object.requirements:
|
for requirement in self.find_requirements_by_name(cdist_object.requirements):
|
||||||
if requirement not in auto_requirement.requirements:
|
requirement_object_all_requirements = list(requirement.requirements) + list(requirement.autorequire)
|
||||||
auto_requirement.requirements.append(requirement)
|
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
|
# 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
|
# it created so that the user can setup dependencies on it as a
|
||||||
# whole without having to know anything about the parents
|
# 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)
|
self.log.debug("Object %s requires %s", cdist_object, required_object)
|
||||||
if required_object not in resolved:
|
if required_object not in resolved:
|
||||||
if required_object in unresolved:
|
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)
|
self._resolve_object_dependencies(required_object, resolved, unresolved)
|
||||||
resolved.append(cdist_object)
|
resolved.append(cdist_object)
|
||||||
unresolved.remove(cdist_object)
|
unresolved.remove(cdist_object)
|
||||||
|
|
|
@ -83,3 +83,9 @@ class AutorequireTestCase(test.CdistTestCase):
|
||||||
self.config.stage_prepare()
|
self.config.stage_prepare()
|
||||||
# raises CircularDependecyError
|
# raises CircularDependecyError
|
||||||
self.config.stage_run()
|
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