Move tasks/blocks to a single parent model
This commit is contained in:
parent
d2b3b2c03e
commit
06d4f4ad0e
12 changed files with 182 additions and 165 deletions
|
@ -244,14 +244,14 @@ class PlayIterator:
|
||||||
if ra != rb:
|
if ra != rb:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return old_s.cur_dep_chain != task._block.get_dep_chain()
|
return old_s.cur_dep_chain != task.get_dep_chain()
|
||||||
|
|
||||||
if task and task._role:
|
if task and task._role:
|
||||||
# if we had a current role, mark that role as completed
|
# if we had a current role, mark that role as completed
|
||||||
if s.cur_role and _roles_are_different(task._role, s.cur_role) and host.name in s.cur_role._had_task_run and not peek:
|
if s.cur_role and _roles_are_different(task._role, s.cur_role) and host.name in s.cur_role._had_task_run and not peek:
|
||||||
s.cur_role._completed[host.name] = True
|
s.cur_role._completed[host.name] = True
|
||||||
s.cur_role = task._role
|
s.cur_role = task._role
|
||||||
s.cur_dep_chain = task._block.get_dep_chain()
|
s.cur_dep_chain = task.get_dep_chain()
|
||||||
|
|
||||||
if not peek:
|
if not peek:
|
||||||
self._host_states[host.name] = s
|
self._host_states[host.name] = s
|
||||||
|
|
|
@ -85,6 +85,8 @@ class Base:
|
||||||
# and initialize the base attributes
|
# and initialize the base attributes
|
||||||
self._initialize_base_attributes()
|
self._initialize_base_attributes()
|
||||||
|
|
||||||
|
self._cached_parent_attrs = dict()
|
||||||
|
|
||||||
# and init vars, avoid using defaults in field declaration as it lives across plays
|
# and init vars, avoid using defaults in field declaration as it lives across plays
|
||||||
self.vars = dict()
|
self.vars = dict()
|
||||||
|
|
||||||
|
@ -111,13 +113,21 @@ class Base:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _generic_g(prop_name, self):
|
def _generic_g(prop_name, self):
|
||||||
method = "_get_attr_%s" % prop_name
|
method = "_get_attr_%s" % prop_name
|
||||||
if hasattr(self, method):
|
try:
|
||||||
value = getattr(self, method)()
|
value = getattr(self, method)()
|
||||||
else:
|
except AttributeError:
|
||||||
try:
|
try:
|
||||||
value = self._attributes[prop_name]
|
value = self._attributes[prop_name]
|
||||||
if value is None and hasattr(self, '_get_parent_attribute'):
|
if value is None:
|
||||||
value = self._get_parent_attribute(prop_name)
|
try:
|
||||||
|
if prop_name in self._cached_parent_attrs:
|
||||||
|
value = self._cached_parent_attrs[prop_name]
|
||||||
|
else:
|
||||||
|
value = self._get_parent_attribute(prop_name)
|
||||||
|
# FIXME: temporarily disabling due to bugs
|
||||||
|
#self._cached_parent_attrs[prop_name] = value
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, prop_name))
|
raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, prop_name))
|
||||||
|
|
||||||
|
@ -151,6 +161,20 @@ class Base:
|
||||||
BASE_ATTRIBUTES[self.__class__.__name__] = base_attributes
|
BASE_ATTRIBUTES[self.__class__.__name__] = base_attributes
|
||||||
return base_attributes
|
return base_attributes
|
||||||
|
|
||||||
|
def dump_me(self, depth=0):
|
||||||
|
if depth == 0:
|
||||||
|
print("DUMPING OBJECT ------------------------------------------------------")
|
||||||
|
print("%s- %s (%s)" % (" " * depth, self.__class__.__name__, self))
|
||||||
|
if hasattr(self, '_parent') and self._parent:
|
||||||
|
self._parent.dump_me(depth+2)
|
||||||
|
dep_chain = self._parent.get_dep_chain()
|
||||||
|
print("%s^ dep chain: %s" % (" "*(depth+2), dep_chain))
|
||||||
|
if dep_chain:
|
||||||
|
for dep in dep_chain:
|
||||||
|
dep.dump_me(depth+2)
|
||||||
|
if hasattr(self, '_play') and self._play:
|
||||||
|
self._play.dump_me(depth+2)
|
||||||
|
|
||||||
def _initialize_base_attributes(self):
|
def _initialize_base_attributes(self):
|
||||||
# each class knows attributes set upon it, see Task.py for example
|
# each class knows attributes set upon it, see Task.py for example
|
||||||
self._attributes = dict()
|
self._attributes = dict()
|
||||||
|
|
|
@ -44,16 +44,15 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
def __init__(self, play=None, parent_block=None, role=None, task_include=None, use_handlers=False, implicit=False):
|
def __init__(self, play=None, parent_block=None, role=None, task_include=None, use_handlers=False, implicit=False):
|
||||||
self._play = play
|
self._play = play
|
||||||
self._role = role
|
self._role = role
|
||||||
self._task_include = None
|
self._parent = None
|
||||||
self._parent_block = None
|
|
||||||
self._dep_chain = None
|
self._dep_chain = None
|
||||||
self._use_handlers = use_handlers
|
self._use_handlers = use_handlers
|
||||||
self._implicit = implicit
|
self._implicit = implicit
|
||||||
|
|
||||||
if task_include:
|
if task_include:
|
||||||
self._task_include = task_include
|
self._parent = task_include
|
||||||
elif parent_block:
|
elif parent_block:
|
||||||
self._parent_block = parent_block
|
self._parent = parent_block
|
||||||
|
|
||||||
super(Block, self).__init__()
|
super(Block, self).__init__()
|
||||||
|
|
||||||
|
@ -65,10 +64,8 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
|
|
||||||
all_vars = self.vars.copy()
|
all_vars = self.vars.copy()
|
||||||
|
|
||||||
if self._parent_block:
|
if self._parent:
|
||||||
all_vars.update(self._parent_block.get_vars())
|
all_vars.update(self._parent.get_vars())
|
||||||
if self._task_include:
|
|
||||||
all_vars.update(self._task_include.get_vars())
|
|
||||||
|
|
||||||
return all_vars
|
return all_vars
|
||||||
|
|
||||||
|
@ -109,7 +106,7 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
play=self._play,
|
play=self._play,
|
||||||
block=self,
|
block=self,
|
||||||
role=self._role,
|
role=self._role,
|
||||||
task_include=self._task_include,
|
task_include=None,
|
||||||
variable_manager=self._variable_manager,
|
variable_manager=self._variable_manager,
|
||||||
loader=self._loader,
|
loader=self._loader,
|
||||||
use_handlers=self._use_handlers,
|
use_handlers=self._use_handlers,
|
||||||
|
@ -124,7 +121,7 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
play=self._play,
|
play=self._play,
|
||||||
block=self,
|
block=self,
|
||||||
role=self._role,
|
role=self._role,
|
||||||
task_include=self._task_include,
|
task_include=None,
|
||||||
variable_manager=self._variable_manager,
|
variable_manager=self._variable_manager,
|
||||||
loader=self._loader,
|
loader=self._loader,
|
||||||
use_handlers=self._use_handlers,
|
use_handlers=self._use_handlers,
|
||||||
|
@ -139,7 +136,7 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
play=self._play,
|
play=self._play,
|
||||||
block=self,
|
block=self,
|
||||||
role=self._role,
|
role=self._role,
|
||||||
task_include=self._task_include,
|
task_include=None,
|
||||||
variable_manager=self._variable_manager,
|
variable_manager=self._variable_manager,
|
||||||
loader=self._loader,
|
loader=self._loader,
|
||||||
use_handlers=self._use_handlers,
|
use_handlers=self._use_handlers,
|
||||||
|
@ -149,10 +146,8 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
|
|
||||||
def get_dep_chain(self):
|
def get_dep_chain(self):
|
||||||
if self._dep_chain is None:
|
if self._dep_chain is None:
|
||||||
if self._parent_block:
|
if self._parent:
|
||||||
return self._parent_block.get_dep_chain()
|
return self._parent.get_dep_chain()
|
||||||
elif self._task_include:
|
|
||||||
return self._task_include._block.get_dep_chain()
|
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
|
@ -162,12 +157,18 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
def _dupe_task_list(task_list, new_block):
|
def _dupe_task_list(task_list, new_block):
|
||||||
new_task_list = []
|
new_task_list = []
|
||||||
for task in task_list:
|
for task in task_list:
|
||||||
if isinstance(task, Block):
|
new_task = task.copy(exclude_parent=True)
|
||||||
new_task = task.copy(exclude_parent=True)
|
if task._parent:
|
||||||
new_task._parent_block = new_block
|
new_task._parent = task._parent.copy(exclude_tasks=True)
|
||||||
|
# go up the parentage tree until we find an
|
||||||
|
# object without a parent and make this new
|
||||||
|
# block their parent
|
||||||
|
cur_obj = new_task
|
||||||
|
while cur_obj._parent:
|
||||||
|
cur_obj = cur_obj._parent
|
||||||
|
cur_obj._parent = new_block
|
||||||
else:
|
else:
|
||||||
new_task = task.copy(exclude_block=True)
|
new_task._parent = new_block
|
||||||
new_task._block = new_block
|
|
||||||
new_task_list.append(new_task)
|
new_task_list.append(new_task)
|
||||||
return new_task_list
|
return new_task_list
|
||||||
|
|
||||||
|
@ -175,27 +176,22 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
new_me._play = self._play
|
new_me._play = self._play
|
||||||
new_me._use_handlers = self._use_handlers
|
new_me._use_handlers = self._use_handlers
|
||||||
|
|
||||||
if self._dep_chain:
|
if self._dep_chain is not None:
|
||||||
new_me._dep_chain = self._dep_chain[:]
|
new_me._dep_chain = self._dep_chain[:]
|
||||||
|
|
||||||
|
new_me._parent = None
|
||||||
|
if self._parent and not exclude_parent:
|
||||||
|
new_me._parent = self._parent.copy(exclude_tasks=exclude_tasks)
|
||||||
|
|
||||||
if not exclude_tasks:
|
if not exclude_tasks:
|
||||||
new_me.block = _dupe_task_list(self.block or [], new_me)
|
new_me.block = _dupe_task_list(self.block or [], new_me)
|
||||||
new_me.rescue = _dupe_task_list(self.rescue or [], new_me)
|
new_me.rescue = _dupe_task_list(self.rescue or [], new_me)
|
||||||
new_me.always = _dupe_task_list(self.always or [], new_me)
|
new_me.always = _dupe_task_list(self.always or [], new_me)
|
||||||
|
|
||||||
new_me._parent_block = None
|
|
||||||
if self._parent_block and not exclude_parent:
|
|
||||||
new_me._parent_block = self._parent_block#.copy(exclude_tasks=exclude_tasks)
|
|
||||||
|
|
||||||
new_me._role = None
|
new_me._role = None
|
||||||
if self._role:
|
if self._role:
|
||||||
new_me._role = self._role
|
new_me._role = self._role
|
||||||
|
|
||||||
new_me._task_include = None
|
|
||||||
if self._task_include:
|
|
||||||
new_me._task_include = self._task_include#.copy(exclude_block=True)
|
|
||||||
#new_me._task_include._block = self._task_include._block.copy(exclude_tasks=True)
|
|
||||||
|
|
||||||
return new_me
|
return new_me
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
|
@ -213,10 +209,9 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
|
|
||||||
if self._role is not None:
|
if self._role is not None:
|
||||||
data['role'] = self._role.serialize()
|
data['role'] = self._role.serialize()
|
||||||
#if self._task_include is not None:
|
if self._parent is not None:
|
||||||
# data['task_include'] = self._task_include.serialize()
|
data['parent'] = self._parent.copy(exclude_tasks=True).serialize()
|
||||||
if self._parent_block is not None:
|
data['parent_type'] = self._parent.__class__.__name__
|
||||||
data['parent_block'] = self._parent_block.copy(exclude_tasks=True).serialize()
|
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -226,7 +221,10 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
serialize method
|
serialize method
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# import is here to avoid import loops
|
||||||
from ansible.playbook.task import Task
|
from ansible.playbook.task import Task
|
||||||
|
from ansible.playbook.task_include import TaskInclude
|
||||||
|
from ansible.playbook.handler_task_include import HandlerTaskInclude
|
||||||
|
|
||||||
# we don't want the full set of attributes (the task lists), as that
|
# we don't want the full set of attributes (the task lists), as that
|
||||||
# would lead to a serialize/deserialize loop
|
# would lead to a serialize/deserialize loop
|
||||||
|
@ -243,19 +241,18 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
r.deserialize(role_data)
|
r.deserialize(role_data)
|
||||||
self._role = r
|
self._role = r
|
||||||
|
|
||||||
# if there was a serialized task include, unpack it too
|
parent_data = data.get('parent')
|
||||||
ti_data = data.get('task_include')
|
if parent_data:
|
||||||
if ti_data:
|
parent_type = data.get('parent_type')
|
||||||
ti = Task()
|
if parent_type == 'Block':
|
||||||
ti.deserialize(ti_data)
|
p = Block()
|
||||||
self._task_include = ti
|
elif parent_type == 'TaskInclude':
|
||||||
|
p = TaskInclude()
|
||||||
pb_data = data.get('parent_block')
|
elif parent_type == 'HandlerTaskInclude':
|
||||||
if pb_data:
|
p = HandlerTaskInclude()
|
||||||
pb = Block()
|
p.deserialize(pb_data)
|
||||||
pb.deserialize(pb_data)
|
self._parent = p
|
||||||
self._parent_block = pb
|
self._dep_chain = self._parent.get_dep_chain()
|
||||||
self._dep_chain = self._parent_block.get_dep_chain()
|
|
||||||
|
|
||||||
def evaluate_conditional(self, templar, all_vars):
|
def evaluate_conditional(self, templar, all_vars):
|
||||||
dep_chain = self.get_dep_chain()
|
dep_chain = self.get_dep_chain()
|
||||||
|
@ -263,24 +260,18 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
for dep in dep_chain:
|
for dep in dep_chain:
|
||||||
if not dep.evaluate_conditional(templar, all_vars):
|
if not dep.evaluate_conditional(templar, all_vars):
|
||||||
return False
|
return False
|
||||||
if self._task_include is not None:
|
if self._parent is not None:
|
||||||
if not self._task_include.evaluate_conditional(templar, all_vars):
|
if not self._parent.evaluate_conditional(templar, all_vars):
|
||||||
return False
|
|
||||||
if self._parent_block is not None:
|
|
||||||
if not self._parent_block.evaluate_conditional(templar, all_vars):
|
|
||||||
return False
|
return False
|
||||||
return super(Block, self).evaluate_conditional(templar, all_vars)
|
return super(Block, self).evaluate_conditional(templar, all_vars)
|
||||||
|
|
||||||
def set_loader(self, loader):
|
def set_loader(self, loader):
|
||||||
self._loader = loader
|
self._loader = loader
|
||||||
if self._parent_block:
|
if self._parent:
|
||||||
self._parent_block.set_loader(loader)
|
self._parent.set_loader(loader)
|
||||||
elif self._role:
|
elif self._role:
|
||||||
self._role.set_loader(loader)
|
self._role.set_loader(loader)
|
||||||
|
|
||||||
if self._task_include:
|
|
||||||
self._task_include.set_loader(loader)
|
|
||||||
|
|
||||||
dep_chain = self.get_dep_chain()
|
dep_chain = self.get_dep_chain()
|
||||||
if dep_chain:
|
if dep_chain:
|
||||||
for dep in dep_chain:
|
for dep in dep_chain:
|
||||||
|
@ -295,14 +286,8 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
try:
|
try:
|
||||||
value = self._attributes[attr]
|
value = self._attributes[attr]
|
||||||
|
|
||||||
if self._parent_block and (value is None or extend):
|
if self._parent and (value is None or extend):
|
||||||
parent_value = getattr(self._parent_block, attr, None)
|
parent_value = getattr(self._parent, attr, None)
|
||||||
if extend:
|
|
||||||
value = self._extend_value(value, parent_value)
|
|
||||||
else:
|
|
||||||
value = parent_value
|
|
||||||
if self._task_include and (value is None or extend):
|
|
||||||
parent_value = getattr(self._task_include, attr, None)
|
|
||||||
if extend:
|
if extend:
|
||||||
value = self._extend_value(value, parent_value)
|
value = self._extend_value(value, parent_value)
|
||||||
else:
|
else:
|
||||||
|
@ -383,3 +368,8 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
def has_tasks(self):
|
def has_tasks(self):
|
||||||
return len(self.block) > 0 or len(self.rescue) > 0 or len(self.always) > 0
|
return len(self.block) > 0 or len(self.rescue) > 0 or len(self.always) > 0
|
||||||
|
|
||||||
|
def get_include_params(self):
|
||||||
|
if self._parent:
|
||||||
|
return self._parent.get_include_params()
|
||||||
|
else:
|
||||||
|
return dict()
|
||||||
|
|
|
@ -46,9 +46,9 @@ def load_list_of_blocks(ds, play, parent_block=None, role=None, task_include=Non
|
||||||
|
|
||||||
block_list = []
|
block_list = []
|
||||||
if ds:
|
if ds:
|
||||||
for block in ds:
|
for block_ds in ds:
|
||||||
b = Block.load(
|
b = Block.load(
|
||||||
block,
|
block_ds,
|
||||||
play=play,
|
play=play,
|
||||||
parent_block=parent_block,
|
parent_block=parent_block,
|
||||||
role=role,
|
role=role,
|
||||||
|
@ -96,7 +96,7 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
|
||||||
play=play,
|
play=play,
|
||||||
parent_block=block,
|
parent_block=block,
|
||||||
role=role,
|
role=role,
|
||||||
task_include=None,
|
task_include=task_include,
|
||||||
use_handlers=use_handlers,
|
use_handlers=use_handlers,
|
||||||
variable_manager=variable_manager,
|
variable_manager=variable_manager,
|
||||||
loader=loader,
|
loader=loader,
|
||||||
|
@ -105,9 +105,19 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
|
||||||
else:
|
else:
|
||||||
if 'include' in task_ds:
|
if 'include' in task_ds:
|
||||||
if use_handlers:
|
if use_handlers:
|
||||||
t = HandlerTaskInclude.load(task_ds, block=block, role=role, task_include=task_include, variable_manager=variable_manager, loader=loader)
|
include_class = HandlerTaskInclude
|
||||||
else:
|
else:
|
||||||
t = TaskInclude.load(task_ds, block=block, role=role, task_include=task_include, variable_manager=variable_manager, loader=loader)
|
include_class = TaskInclude
|
||||||
|
|
||||||
|
t = include_class.load(
|
||||||
|
task_ds,
|
||||||
|
block=block,
|
||||||
|
role=role,
|
||||||
|
task_include=None,
|
||||||
|
variable_manager=variable_manager,
|
||||||
|
loader=loader
|
||||||
|
)
|
||||||
|
|
||||||
all_vars = variable_manager.get_vars(loader=loader, play=play, task=t)
|
all_vars = variable_manager.get_vars(loader=loader, play=play, task=t)
|
||||||
templar = Templar(loader=loader, variables=all_vars)
|
templar = Templar(loader=loader, variables=all_vars)
|
||||||
|
|
||||||
|
@ -134,6 +144,9 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
|
||||||
parent_include = task_include
|
parent_include = task_include
|
||||||
cumulative_path = None
|
cumulative_path = None
|
||||||
while parent_include is not None:
|
while parent_include is not None:
|
||||||
|
if not isinstance(parent_include, TaskInclude):
|
||||||
|
parent_include = parent_include._parent
|
||||||
|
continue
|
||||||
parent_include_dir = templar.template(os.path.dirname(parent_include.args.get('_raw_params')))
|
parent_include_dir = templar.template(os.path.dirname(parent_include.args.get('_raw_params')))
|
||||||
if cumulative_path is None:
|
if cumulative_path is None:
|
||||||
cumulative_path = parent_include_dir
|
cumulative_path = parent_include_dir
|
||||||
|
@ -149,7 +162,7 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
|
||||||
if os.path.exists(include_file):
|
if os.path.exists(include_file):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
parent_include = parent_include._task_include
|
parent_include = parent_include._parent
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
include_target = templar.template(t.args['_raw_params'])
|
include_target = templar.template(t.args['_raw_params'])
|
||||||
|
@ -195,8 +208,8 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
|
||||||
included_blocks = load_list_of_blocks(
|
included_blocks = load_list_of_blocks(
|
||||||
data,
|
data,
|
||||||
play=play,
|
play=play,
|
||||||
parent_block=block,
|
parent_block=None,
|
||||||
task_include=t,
|
task_include=t.copy(),
|
||||||
role=role,
|
role=role,
|
||||||
use_handlers=use_handlers,
|
use_handlers=use_handlers,
|
||||||
loader=loader,
|
loader=loader,
|
||||||
|
@ -213,8 +226,8 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
|
||||||
if len(tags) > 0:
|
if len(tags) > 0:
|
||||||
if len(t.tags) > 0:
|
if len(t.tags) > 0:
|
||||||
raise AnsibleParserError(
|
raise AnsibleParserError(
|
||||||
"Include tasks should not specify tags in more than one way (both via args and directly on the task)." \
|
"Include tasks should not specify tags in more than one way (both via args and directly on the task). " \
|
||||||
" Mixing tag specify styles is prohibited for whole import hierarchy, not only for single import statement",
|
"Mixing styles in which tags are specified is prohibited for whole import hierarchy, not only for single import statement",
|
||||||
obj=task_ds,
|
obj=task_ds,
|
||||||
suppress_extended_error=True,
|
suppress_extended_error=True,
|
||||||
)
|
)
|
||||||
|
|
|
@ -22,6 +22,7 @@ __metaclass__ = type
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from ansible.errors import AnsibleError
|
from ansible.errors import AnsibleError
|
||||||
|
from ansible.playbook.task_include import TaskInclude
|
||||||
from ansible.template import Templar
|
from ansible.template import Templar
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -86,16 +87,20 @@ class IncludedFile:
|
||||||
if loop_var in include_result:
|
if loop_var in include_result:
|
||||||
task_vars[loop_var] = include_variables[loop_var] = include_result[loop_var]
|
task_vars[loop_var] = include_variables[loop_var] = include_result[loop_var]
|
||||||
|
|
||||||
|
include_file = None
|
||||||
if original_task:
|
if original_task:
|
||||||
if original_task.static:
|
if original_task.static:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if original_task._task_include:
|
if original_task._parent:
|
||||||
# handle relative includes by walking up the list of parent include
|
# handle relative includes by walking up the list of parent include
|
||||||
# tasks and checking the relative result to see if it exists
|
# tasks and checking the relative result to see if it exists
|
||||||
parent_include = original_task._task_include
|
parent_include = original_task._parent
|
||||||
cumulative_path = None
|
cumulative_path = None
|
||||||
while parent_include is not None:
|
while parent_include is not None:
|
||||||
|
if not isinstance(parent_include, TaskInclude):
|
||||||
|
parent_include = parent_include._parent
|
||||||
|
continue
|
||||||
parent_include_dir = templar.template(os.path.dirname(parent_include.args.get('_raw_params')))
|
parent_include_dir = templar.template(os.path.dirname(parent_include.args.get('_raw_params')))
|
||||||
if cumulative_path is None:
|
if cumulative_path is None:
|
||||||
cumulative_path = parent_include_dir
|
cumulative_path = parent_include_dir
|
||||||
|
@ -111,14 +116,14 @@ class IncludedFile:
|
||||||
if os.path.exists(include_file):
|
if os.path.exists(include_file):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
parent_include = parent_include._task_include
|
parent_include = parent_include._parent
|
||||||
elif original_task._role:
|
|
||||||
|
if include_file is None:
|
||||||
|
if original_task._role:
|
||||||
include_target = templar.template(include_result['include'])
|
include_target = templar.template(include_result['include'])
|
||||||
include_file = loader.path_dwim_relative(original_task._role._role_path, 'tasks', include_target)
|
include_file = loader.path_dwim_relative(original_task._role._role_path, 'tasks', include_target)
|
||||||
else:
|
else:
|
||||||
include_file = loader.path_dwim(include_result['include'])
|
include_file = loader.path_dwim(include_result['include'])
|
||||||
else:
|
|
||||||
include_file = loader.path_dwim(include_result['include'])
|
|
||||||
|
|
||||||
include_file = templar.template(include_file)
|
include_file = templar.template(include_file)
|
||||||
inc_file = IncludedFile(include_file, include_variables, original_task)
|
inc_file = IncludedFile(include_file, include_variables, original_task)
|
||||||
|
|
|
@ -353,7 +353,9 @@ class Role(Base, Become, Conditional, Taggable):
|
||||||
block_list.extend(dep_blocks)
|
block_list.extend(dep_blocks)
|
||||||
|
|
||||||
for task_block in self._task_blocks:
|
for task_block in self._task_blocks:
|
||||||
new_task_block = task_block.copy()
|
new_task_block = task_block.copy(exclude_parent=True)
|
||||||
|
if task_block._parent:
|
||||||
|
new_task_block._parent = task_block._parent.copy()
|
||||||
new_task_block._dep_chain = new_dep_chain
|
new_task_block._dep_chain = new_dep_chain
|
||||||
new_task_block._play = play
|
new_task_block._play = play
|
||||||
block_list.append(new_task_block)
|
block_list.append(new_task_block)
|
||||||
|
|
|
@ -92,9 +92,13 @@ class Task(Base, Conditional, Taggable, Become):
|
||||||
def __init__(self, block=None, role=None, task_include=None):
|
def __init__(self, block=None, role=None, task_include=None):
|
||||||
''' constructors a task, without the Task.load classmethod, it will be pretty blank '''
|
''' constructors a task, without the Task.load classmethod, it will be pretty blank '''
|
||||||
|
|
||||||
self._block = block
|
self._role = role
|
||||||
self._role = role
|
self._parent = None
|
||||||
self._task_include = task_include
|
|
||||||
|
if task_include:
|
||||||
|
self._parent = task_include
|
||||||
|
else:
|
||||||
|
self._parent = block
|
||||||
|
|
||||||
super(Task, self).__init__()
|
super(Task, self).__init__()
|
||||||
|
|
||||||
|
@ -242,10 +246,8 @@ class Task(Base, Conditional, Taggable, Become):
|
||||||
the block and task include (if any) to which this task belongs.
|
the block and task include (if any) to which this task belongs.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if self._block:
|
if self._parent:
|
||||||
self._block.post_validate(templar)
|
self._parent.post_validate(templar)
|
||||||
if self._task_include:
|
|
||||||
self._task_include.post_validate(templar)
|
|
||||||
|
|
||||||
super(Task, self).post_validate(templar)
|
super(Task, self).post_validate(templar)
|
||||||
|
|
||||||
|
@ -304,10 +306,8 @@ class Task(Base, Conditional, Taggable, Become):
|
||||||
|
|
||||||
def get_vars(self):
|
def get_vars(self):
|
||||||
all_vars = dict()
|
all_vars = dict()
|
||||||
if self._block:
|
if self._parent:
|
||||||
all_vars.update(self._block.get_vars())
|
all_vars.update(self._parent.get_vars())
|
||||||
if self._task_include:
|
|
||||||
all_vars.update(self._task_include.get_vars())
|
|
||||||
|
|
||||||
all_vars.update(self.vars)
|
all_vars.update(self.vars)
|
||||||
|
|
||||||
|
@ -320,56 +320,55 @@ class Task(Base, Conditional, Taggable, Become):
|
||||||
|
|
||||||
def get_include_params(self):
|
def get_include_params(self):
|
||||||
all_vars = dict()
|
all_vars = dict()
|
||||||
if self._task_include:
|
if self._parent:
|
||||||
all_vars.update(self._task_include.get_include_params())
|
all_vars.update(self._parent.get_include_params())
|
||||||
if self.action == 'include':
|
if self.action == 'include':
|
||||||
all_vars.update(self.vars)
|
all_vars.update(self.vars)
|
||||||
return all_vars
|
return all_vars
|
||||||
|
|
||||||
def copy(self, exclude_block=False, exclude_tasks=False):
|
def copy(self, exclude_parent=False, exclude_tasks=False):
|
||||||
new_me = super(Task, self).copy()
|
new_me = super(Task, self).copy()
|
||||||
|
|
||||||
new_me._block = None
|
new_me._parent = None
|
||||||
if self._block and not exclude_block:
|
if self._parent and not exclude_parent:
|
||||||
new_me._block = self._block#.copy(exclude_tasks=exclude_tasks)
|
new_me._parent = self._parent.copy(exclude_tasks=exclude_tasks)
|
||||||
|
|
||||||
new_me._role = None
|
new_me._role = None
|
||||||
if self._role:
|
if self._role:
|
||||||
new_me._role = self._role
|
new_me._role = self._role
|
||||||
|
|
||||||
new_me._task_include = None
|
|
||||||
if self._task_include:
|
|
||||||
new_me._task_include = self._task_include#.copy(exclude_block=True)
|
|
||||||
#new_me._task_include._block = self._task_include._block.copy(exclude_tasks=True)
|
|
||||||
|
|
||||||
return new_me
|
return new_me
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
data = super(Task, self).serialize()
|
data = super(Task, self).serialize()
|
||||||
|
|
||||||
if self._block:
|
if self._parent:
|
||||||
data['block'] = self._block.serialize()
|
data['parent'] = self._parent.serialize()
|
||||||
|
data['parent_type'] = self._parent.__class__.__name__
|
||||||
|
|
||||||
if self._role:
|
if self._role:
|
||||||
data['role'] = self._role.serialize()
|
data['role'] = self._role.serialize()
|
||||||
|
|
||||||
if self._task_include:
|
|
||||||
data['task_include'] = self._task_include.serialize()
|
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def deserialize(self, data):
|
def deserialize(self, data):
|
||||||
|
|
||||||
# import is here to avoid import loops
|
# import is here to avoid import loops
|
||||||
#from ansible.playbook.task_include import TaskInclude
|
from ansible.playbook.task_include import TaskInclude
|
||||||
|
from ansible.playbook.handler_task_include import HandlerTaskInclude
|
||||||
|
|
||||||
block_data = data.get('block')
|
parent_data = data.get('parent', None)
|
||||||
|
if parent_data:
|
||||||
if block_data:
|
parent_type = data.get('parent_type')
|
||||||
b = Block()
|
if parent_type == 'Block':
|
||||||
b.deserialize(block_data)
|
p = Block()
|
||||||
self._block = b
|
elif parent_type == 'TaskInclude':
|
||||||
del data['block']
|
p = TaskInclude()
|
||||||
|
elif parent_type == 'HandlerTaskInclude':
|
||||||
|
p = HandlerTaskInclude()
|
||||||
|
p.deserialize(parent_data)
|
||||||
|
self._parent = p
|
||||||
|
del data['parent']
|
||||||
|
|
||||||
role_data = data.get('role')
|
role_data = data.get('role')
|
||||||
if role_data:
|
if role_data:
|
||||||
|
@ -378,22 +377,11 @@ class Task(Base, Conditional, Taggable, Become):
|
||||||
self._role = r
|
self._role = r
|
||||||
del data['role']
|
del data['role']
|
||||||
|
|
||||||
ti_data = data.get('task_include')
|
|
||||||
if ti_data:
|
|
||||||
#ti = TaskInclude()
|
|
||||||
ti = Task()
|
|
||||||
ti.deserialize(ti_data)
|
|
||||||
self._task_include = ti
|
|
||||||
del data['task_include']
|
|
||||||
|
|
||||||
super(Task, self).deserialize(data)
|
super(Task, self).deserialize(data)
|
||||||
|
|
||||||
def evaluate_conditional(self, templar, all_vars):
|
def evaluate_conditional(self, templar, all_vars):
|
||||||
if self._block is not None:
|
if self._parent is not None:
|
||||||
if not self._block.evaluate_conditional(templar, all_vars):
|
if not self._parent.evaluate_conditional(templar, all_vars):
|
||||||
return False
|
|
||||||
if self._task_include is not None:
|
|
||||||
if not self._task_include.evaluate_conditional(templar, all_vars):
|
|
||||||
return False
|
return False
|
||||||
return super(Task, self).evaluate_conditional(templar, all_vars)
|
return super(Task, self).evaluate_conditional(templar, all_vars)
|
||||||
|
|
||||||
|
@ -406,10 +394,8 @@ class Task(Base, Conditional, Taggable, Become):
|
||||||
|
|
||||||
self._loader = loader
|
self._loader = loader
|
||||||
|
|
||||||
if self._block:
|
if self._parent:
|
||||||
self._block.set_loader(loader)
|
self._parent.set_loader(loader)
|
||||||
if self._task_include:
|
|
||||||
self._task_include.set_loader(loader)
|
|
||||||
|
|
||||||
def _get_parent_attribute(self, attr, extend=False):
|
def _get_parent_attribute(self, attr, extend=False):
|
||||||
'''
|
'''
|
||||||
|
@ -419,14 +405,8 @@ class Task(Base, Conditional, Taggable, Become):
|
||||||
try:
|
try:
|
||||||
value = self._attributes[attr]
|
value = self._attributes[attr]
|
||||||
|
|
||||||
if self._block and (value is None or extend):
|
if self._parent and (value is None or extend):
|
||||||
parent_value = getattr(self._block, attr, None)
|
parent_value = getattr(self._parent, attr, None)
|
||||||
if extend:
|
|
||||||
value = self._extend_value(value, parent_value)
|
|
||||||
else:
|
|
||||||
value = parent_value
|
|
||||||
if self._task_include and (value is None or extend):
|
|
||||||
parent_value = getattr(self._task_include, attr, None)
|
|
||||||
if extend:
|
if extend:
|
||||||
value = self._extend_value(value, parent_value)
|
value = self._extend_value(value, parent_value)
|
||||||
else:
|
else:
|
||||||
|
@ -458,6 +438,11 @@ class Task(Base, Conditional, Taggable, Become):
|
||||||
def _get_attr_loop_control(self):
|
def _get_attr_loop_control(self):
|
||||||
return self._attributes['loop_control']
|
return self._attributes['loop_control']
|
||||||
|
|
||||||
|
def get_dep_chain(self):
|
||||||
|
if self._parent:
|
||||||
|
return self._parent.get_dep_chain()
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def get_search_path(self):
|
def get_search_path(self):
|
||||||
'''
|
'''
|
||||||
|
@ -466,7 +451,7 @@ class Task(Base, Conditional, Taggable, Become):
|
||||||
'''
|
'''
|
||||||
path_stack = []
|
path_stack = []
|
||||||
|
|
||||||
dep_chain = self._block.get_dep_chain()
|
dep_chain = self.get_dep_chain()
|
||||||
# inside role: add the dependency chain from current to dependant
|
# inside role: add the dependency chain from current to dependant
|
||||||
if dep_chain:
|
if dep_chain:
|
||||||
path_stack.extend(reversed([x._role_path for x in dep_chain]))
|
path_stack.extend(reversed([x._role_path for x in dep_chain]))
|
||||||
|
|
|
@ -55,10 +55,8 @@ class TaskInclude(Task):
|
||||||
they are params to the included tasks.
|
they are params to the included tasks.
|
||||||
'''
|
'''
|
||||||
all_vars = dict()
|
all_vars = dict()
|
||||||
if self._block:
|
if self._parent:
|
||||||
all_vars.update(self._block.get_vars())
|
all_vars.update(self._parent.get_vars())
|
||||||
if self._task_include:
|
|
||||||
all_vars.update(self._task_include.get_vars())
|
|
||||||
|
|
||||||
all_vars.update(self.vars)
|
all_vars.update(self.vars)
|
||||||
all_vars.update(self.args)
|
all_vars.update(self.args)
|
||||||
|
|
|
@ -574,9 +574,9 @@ class StrategyBase:
|
||||||
|
|
||||||
block_list = load_list_of_blocks(
|
block_list = load_list_of_blocks(
|
||||||
data,
|
data,
|
||||||
play=included_file._task._block._play,
|
play=iterator._play,
|
||||||
parent_block=None,
|
parent_block=None,
|
||||||
task_include=included_file._task,
|
task_include=None,
|
||||||
role=included_file._task._role,
|
role=included_file._task._role,
|
||||||
use_handlers=is_handler,
|
use_handlers=is_handler,
|
||||||
loader=self._loader,
|
loader=self._loader,
|
||||||
|
@ -602,9 +602,9 @@ class StrategyBase:
|
||||||
# set the vars for this task from those specified as params to the include
|
# set the vars for this task from those specified as params to the include
|
||||||
for b in block_list:
|
for b in block_list:
|
||||||
# first make a copy of the including task, so that each has a unique copy to modify
|
# first make a copy of the including task, so that each has a unique copy to modify
|
||||||
b._task_include = b._task_include.copy()
|
b._parent = included_file._task.copy()
|
||||||
# then we create a temporary set of vars to ensure the variable reference is unique
|
# then we create a temporary set of vars to ensure the variable reference is unique
|
||||||
temp_vars = b._task_include.vars.copy()
|
temp_vars = b._parent.vars.copy()
|
||||||
temp_vars.update(included_file._args.copy())
|
temp_vars.update(included_file._args.copy())
|
||||||
# pop tags out of the include args, if they were specified there, and assign
|
# pop tags out of the include args, if they were specified there, and assign
|
||||||
# them to the include. If the include already had tags specified, we raise an
|
# them to the include. If the include already had tags specified, we raise an
|
||||||
|
@ -613,12 +613,12 @@ class StrategyBase:
|
||||||
if isinstance(tags, string_types):
|
if isinstance(tags, string_types):
|
||||||
tags = tags.split(',')
|
tags = tags.split(',')
|
||||||
if len(tags) > 0:
|
if len(tags) > 0:
|
||||||
if len(b._task_include.tags) > 0:
|
if len(b._parent.tags) > 0:
|
||||||
raise AnsibleParserError("Include tasks should not specify tags in more than one way (both via args and directly on the task). Mixing tag specify styles is prohibited for whole import hierarchy, not only for single import statement",
|
raise AnsibleParserError("Include tasks should not specify tags in more than one way (both via args and directly on the task). Mixing tag specify styles is prohibited for whole import hierarchy, not only for single import statement",
|
||||||
obj=included_file._task._ds)
|
obj=included_file._task._ds)
|
||||||
display.deprecated("You should not specify tags in the include parameters. All tags should be specified using the task-level option")
|
display.deprecated("You should not specify tags in the include parameters. All tags should be specified using the task-level option")
|
||||||
b._task_include.tags = tags
|
b._parent.tags = tags
|
||||||
b._task_include.vars = temp_vars
|
b._parent.vars = temp_vars
|
||||||
|
|
||||||
# finally, send the callback and return the list of blocks loaded
|
# finally, send the callback and return the list of blocks loaded
|
||||||
self._tqm.send_callback('v2_playbook_on_include', included_file)
|
self._tqm.send_callback('v2_playbook_on_include', included_file)
|
||||||
|
|
|
@ -316,7 +316,7 @@ class StrategyModule(StrategyBase):
|
||||||
final_block = new_block.filter_tagged_tasks(play_context, task_vars)
|
final_block = new_block.filter_tagged_tasks(play_context, task_vars)
|
||||||
display.debug("done filtering new block on tags")
|
display.debug("done filtering new block on tags")
|
||||||
|
|
||||||
noop_block = Block(parent_block=task._block)
|
noop_block = Block(parent_block=task._parent)
|
||||||
noop_block.block = [noop_task for t in new_block.block]
|
noop_block.block = [noop_task for t in new_block.block]
|
||||||
noop_block.always = [noop_task for t in new_block.always]
|
noop_block.always = [noop_task for t in new_block.always]
|
||||||
noop_block.rescue = [noop_task for t in new_block.rescue]
|
noop_block.rescue = [noop_task for t in new_block.rescue]
|
||||||
|
|
|
@ -237,7 +237,7 @@ class VariableManager:
|
||||||
# sure it sees its defaults above any other roles, as we previously
|
# sure it sees its defaults above any other roles, as we previously
|
||||||
# (v1) made sure each task had a copy of its roles default vars
|
# (v1) made sure each task had a copy of its roles default vars
|
||||||
if task and task._role is not None:
|
if task and task._role is not None:
|
||||||
all_vars = combine_vars(all_vars, task._role.get_default_vars(dep_chain=task._block.get_dep_chain()))
|
all_vars = combine_vars(all_vars, task._role.get_default_vars(dep_chain=task.get_dep_chain()))
|
||||||
|
|
||||||
if host:
|
if host:
|
||||||
# next, if a host is specified, we load any vars from group_vars
|
# next, if a host is specified, we load any vars from group_vars
|
||||||
|
@ -334,7 +334,7 @@ class VariableManager:
|
||||||
# vars (which will look at parent blocks/task includes)
|
# vars (which will look at parent blocks/task includes)
|
||||||
if task:
|
if task:
|
||||||
if task._role:
|
if task._role:
|
||||||
all_vars = combine_vars(all_vars, task._role.get_vars(task._block._dep_chain, include_params=False))
|
all_vars = combine_vars(all_vars, task._role.get_vars(task.get_dep_chain(), include_params=False))
|
||||||
all_vars = combine_vars(all_vars, task.get_vars())
|
all_vars = combine_vars(all_vars, task.get_vars())
|
||||||
|
|
||||||
# next, we merge in the vars cache (include vars) and nonpersistent
|
# next, we merge in the vars cache (include vars) and nonpersistent
|
||||||
|
@ -346,7 +346,7 @@ class VariableManager:
|
||||||
# next, we merge in role params and task include params
|
# next, we merge in role params and task include params
|
||||||
if task:
|
if task:
|
||||||
if task._role:
|
if task._role:
|
||||||
all_vars = combine_vars(all_vars, task._role.get_role_params(task._block.get_dep_chain()))
|
all_vars = combine_vars(all_vars, task._role.get_role_params(task.get_dep_chain()))
|
||||||
|
|
||||||
# special case for include tasks, where the include params
|
# special case for include tasks, where the include params
|
||||||
# may be specified in the vars field for the task, which should
|
# may be specified in the vars field for the task, which should
|
||||||
|
|
|
@ -121,7 +121,7 @@ class TestPlayIterator(unittest.TestCase):
|
||||||
|
|
||||||
# lookup up an original task
|
# lookup up an original task
|
||||||
target_task = p._entries[0].tasks[0].block[0]
|
target_task = p._entries[0].tasks[0].block[0]
|
||||||
task_copy = target_task.copy(exclude_block=True)
|
task_copy = target_task.copy(exclude_parent=True)
|
||||||
found_task = itr.get_original_task(hosts[0], task_copy)
|
found_task = itr.get_original_task(hosts[0], task_copy)
|
||||||
self.assertEqual(target_task, found_task)
|
self.assertEqual(target_task, found_task)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue