Add play to the parent object structures for inheritence in v2

pull/10838/merge
James Cammarata 10 years ago
parent fb96173d10
commit aafda44bb3

@ -324,6 +324,20 @@ class Base:
# restore the UUID field
setattr(self, '_uuid', data.get('uuid'))
def _extend_value(self, value, new_value):
'''
Will extend the value given with new_value (and will turn both
into lists if they are not so already). The values are run through
a set to remove duplicate values.
'''
if not isinstance(value, list):
value = [ value ]
if not isinstance(new_value, list):
new_value = [ new_value ]
return list(set(value + new_value))
def __getstate__(self):
return self.serialize()

@ -37,10 +37,11 @@ class Block(Base, Become, Conditional, Taggable):
# similar to the 'else' clause for exceptions
#_otherwise = FieldAttribute(isa='list')
def __init__(self, parent_block=None, role=None, task_include=None, use_handlers=False):
self._parent_block = parent_block
def __init__(self, play=None, parent_block=None, role=None, task_include=None, use_handlers=False):
self._play = play
self._role = role
self._task_include = task_include
self._parent_block = parent_block
self._use_handlers = use_handlers
self._dep_chain = []
@ -65,8 +66,8 @@ class Block(Base, Become, Conditional, Taggable):
return all_vars
@staticmethod
def load(data, parent_block=None, role=None, task_include=None, use_handlers=False, variable_manager=None, loader=None):
b = Block(parent_block=parent_block, role=role, task_include=task_include, use_handlers=use_handlers)
def load(data, play, parent_block=None, role=None, task_include=None, use_handlers=False, variable_manager=None, loader=None):
b = Block(play=play, parent_block=parent_block, role=role, task_include=task_include, use_handlers=use_handlers)
return b.load_data(data, variable_manager=variable_manager, loader=loader)
def preprocess_data(self, ds):
@ -92,6 +93,7 @@ class Block(Base, Become, Conditional, Taggable):
def _load_block(self, attr, ds):
return load_list_of_tasks(
ds,
play=self._play,
block=self,
role=self._role,
task_include=self._task_include,
@ -103,6 +105,7 @@ class Block(Base, Become, Conditional, Taggable):
def _load_rescue(self, attr, ds):
return load_list_of_tasks(
ds,
play=self._play,
block=self,
role=self._role,
task_include=self._task_include,
@ -114,6 +117,7 @@ class Block(Base, Become, Conditional, Taggable):
def _load_always(self, attr, ds):
return load_list_of_tasks(
ds,
play=self._play,
block=self,
role=self._role,
task_include=self._task_include,
@ -126,6 +130,7 @@ class Block(Base, Become, Conditional, Taggable):
#def _load_otherwise(self, attr, ds):
# return load_list_of_tasks(
# ds,
# play=self._play,
# block=self,
# role=self._role,
# task_include=self._task_include,
@ -148,6 +153,7 @@ class Block(Base, Become, Conditional, Taggable):
return new_task_list
new_me = super(Block, self).copy()
new_me._play = self._play
new_me._use_handlers = self._use_handlers
new_me._dep_chain = self._dep_chain[:]
@ -248,24 +254,44 @@ class Block(Base, Become, Conditional, Taggable):
for dep in self._dep_chain:
dep.set_loader(loader)
def _get_parent_attribute(self, attr):
def _get_parent_attribute(self, attr, extend=False):
'''
Generic logic to get the attribute or parent attribute for a block value.
'''
value = self._attributes[attr]
if not value:
if self._parent_block:
value = getattr(self._parent_block, attr)
elif self._role:
value = getattr(self._role, attr)
if not value and len(self._dep_chain):
reverse_dep_chain = self._dep_chain[:]
reverse_dep_chain.reverse()
for dep in reverse_dep_chain:
value = getattr(dep, attr)
if value:
break
if self._parent_block and (not value or extend):
parent_value = getattr(self._parent_block, attr)
if extend:
value = self._extend_value(value, parent_value)
else:
value = parent_value
if self._task_include and (not value or extend):
parent_value = getattr(self._task_include, attr)
if extend:
value = self._extend_value(value, parent_value)
else:
value = parent_value
if self._role and (not value or extend):
parent_value = getattr(self._role, attr)
if len(self._dep_chain) and (not value or extend):
reverse_dep_chain = self._dep_chain[:]
reverse_dep_chain.reverse()
for dep in reverse_dep_chain:
dep_value = getattr(dep, attr)
if extend:
value = self._extend_value(value, parent_value)
else:
value = parent_value
if value and not extend:
break
if self._play and (not value or extend):
parent_value = getattr(self._play, attr)
if extend:
value = self._extend_value(value, parent_value)
else:
value = parent_value
return value

@ -26,7 +26,7 @@ from ansible.errors import AnsibleParserError
from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject, AnsibleSequence
def load_list_of_blocks(ds, parent_block=None, role=None, task_include=None, use_handlers=False, variable_manager=None, loader=None):
def load_list_of_blocks(ds, play, parent_block=None, role=None, task_include=None, use_handlers=False, variable_manager=None, loader=None):
'''
Given a list of mixed task/block data (parsed from YAML),
return a list of Block() objects, where implicit blocks
@ -43,6 +43,7 @@ def load_list_of_blocks(ds, parent_block=None, role=None, task_include=None, use
for block in ds:
b = Block.load(
block,
play=play,
parent_block=parent_block,
role=role,
task_include=task_include,
@ -55,7 +56,7 @@ def load_list_of_blocks(ds, parent_block=None, role=None, task_include=None, use
return block_list
def load_list_of_tasks(ds, block=None, role=None, task_include=None, use_handlers=False, variable_manager=None, loader=None):
def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_handlers=False, variable_manager=None, loader=None):
'''
Given a list of task datastructures (parsed from YAML),
return a list of Task() or TaskInclude() objects.
@ -76,6 +77,7 @@ def load_list_of_tasks(ds, block=None, role=None, task_include=None, use_handler
if 'block' in task:
t = Block.load(
task,
play=play,
parent_block=block,
role=role,
task_include=task_include,

@ -145,28 +145,28 @@ class Play(Base, Taggable, Become):
Loads a list of blocks from a list which may be mixed tasks/blocks.
Bare tasks outside of a block are given an implicit block.
'''
return load_list_of_blocks(ds, variable_manager=self._variable_manager, loader=self._loader)
return load_list_of_blocks(ds=ds, play=self, variable_manager=self._variable_manager, loader=self._loader)
def _load_pre_tasks(self, attr, ds):
'''
Loads a list of blocks from a list which may be mixed tasks/blocks.
Bare tasks outside of a block are given an implicit block.
'''
return load_list_of_blocks(ds, variable_manager=self._variable_manager, loader=self._loader)
return load_list_of_blocks(ds=ds, play=self, variable_manager=self._variable_manager, loader=self._loader)
def _load_post_tasks(self, attr, ds):
'''
Loads a list of blocks from a list which may be mixed tasks/blocks.
Bare tasks outside of a block are given an implicit block.
'''
return load_list_of_blocks(ds, variable_manager=self._variable_manager, loader=self._loader)
return load_list_of_blocks(ds=ds, play=self, variable_manager=self._variable_manager, loader=self._loader)
def _load_handlers(self, attr, ds):
'''
Loads a list of blocks from a list which may be mixed handlers/blocks.
Bare handlers outside of a block are given an implicit block.
'''
return load_list_of_blocks(ds, use_handlers=True, variable_manager=self._variable_manager, loader=self._loader)
return load_list_of_blocks(ds=ds, play=self, use_handlers=True, variable_manager=self._variable_manager, loader=self._loader)
def _load_roles(self, attr, ds):
'''
@ -196,7 +196,7 @@ class Play(Base, Taggable, Become):
if len(self.roles) > 0:
for r in self.roles:
block_list.extend(r.compile())
block_list.extend(r.compile(play=self))
return block_list

@ -79,6 +79,7 @@ class Role(Base, Become, Conditional, Taggable):
self._loader = None
self._metadata = None
self._play = None
self._parents = []
self._dependencies = []
self._task_blocks = []
@ -163,11 +164,11 @@ class Role(Base, Become, Conditional, Taggable):
task_data = self._load_role_yaml('tasks')
if task_data:
self._task_blocks = load_list_of_blocks(task_data, role=self, loader=self._loader)
self._task_blocks = load_list_of_blocks(task_data, play=None, role=self, loader=self._loader)
handler_data = self._load_role_yaml('handlers')
if handler_data:
self._handler_blocks = load_list_of_blocks(handler_data, role=self, loader=self._loader)
self._handler_blocks = load_list_of_blocks(handler_data, play=None, role=self, loader=self._loader)
# vars and default vars are regular dictionaries
self._role_vars = self._load_role_yaml('vars')
@ -293,7 +294,7 @@ class Role(Base, Become, Conditional, Taggable):
return self._had_task_run and self._completed
def compile(self, dep_chain=[]):
def compile(self, play, dep_chain=[]):
'''
Returns the task list for this role, which is created by first
recursively compiling the tasks for all direct dependencies, and
@ -311,10 +312,11 @@ class Role(Base, Become, Conditional, Taggable):
deps = self.get_direct_dependencies()
for dep in deps:
dep_blocks = dep.compile(dep_chain=new_dep_chain)
dep_blocks = dep.compile(play=play, dep_chain=new_dep_chain)
for dep_block in dep_blocks:
new_dep_block = dep_block.copy()
new_dep_block._dep_chain = new_dep_chain
new_dep_block._play = play
block_list.append(new_dep_block)
block_list.extend(self._task_blocks)

@ -26,7 +26,7 @@ from ansible.template import Templar
class Taggable:
untagged = set(['untagged'])
_tags = FieldAttribute(isa='list', default=[])
_tags = FieldAttribute(isa='list', default=None)
def __init__(self):
super(Taggable, self).__init__()
@ -44,9 +44,11 @@ class Taggable:
Override for the 'tags' getattr fetcher, used from Base.
'''
tags = self._attributes['tags']
if tags is None:
tags = []
if hasattr(self, '_get_parent_attribute'):
tags.extend(self._get_parent_attribute('tags'))
return list(set(tags))
tags = self._get_parent_attribute('tags', extend=True)
return tags
def evaluate_tags(self, only_tags, skip_tags, all_vars):
''' this checks if the current item should be executed depending on tag options '''

@ -205,16 +205,6 @@ class Task(Base, Conditional, Taggable, Become):
del all_vars['when']
return all_vars
# no longer used, as blocks are the lowest level of compilation now
#def compile(self):
# '''
# For tasks, this is just a dummy method returning an array
# with 'self' in it, so we don't have to care about task types
# further up the chain.
# '''
#
# return [self]
def copy(self, exclude_block=False):
new_me = super(Task, self).copy()
@ -299,12 +289,22 @@ class Task(Base, Conditional, Taggable, Become):
if self._task_include:
self._task_include.set_loader(loader)
def _get_parent_attribute(self, attr):
def _get_parent_attribute(self, attr, extend=False):
'''
Generic logic to get the attribute or parent attribute for a task value.
'''
value = self._attributes[attr]
if not value and self._block:
value = getattr(self._block, attr)
if self._block and (not value or extend):
parent_value = getattr(self._block, attr)
if extend:
value = self._extend_value(value, parent_value)
else:
value = parent_value
if self._task_include and (not value or extend):
parent_value = getattr(self._task_include, attr)
if extend:
value = self._extend_value(value, parent_value)
else:
value = parent_value
return value

@ -308,6 +308,7 @@ class StrategyBase:
is_handler = isinstance(included_file._task, Handler)
block_list = load_list_of_blocks(
data,
play=included_file._task._block._play,
parent_block=included_file._task._block,
task_include=included_file._task,
role=included_file._task._role,

@ -1,10 +1,17 @@
- hosts: localhost
gather_facts: no
vars:
a: "tags"
tags:
- play
tasks:
- block:
- debug: msg="this is the tagged block"
tags:
- block
- include: include.yml
tags:
- include
- block:
- debug: msg="tagged debug from second block"
tags:

Loading…
Cancel
Save