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 # restore the UUID field
setattr(self, '_uuid', data.get('uuid')) 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): def __getstate__(self):
return self.serialize() return self.serialize()

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

@ -26,7 +26,7 @@ from ansible.errors import AnsibleParserError
from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject, AnsibleSequence 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), Given a list of mixed task/block data (parsed from YAML),
return a list of Block() objects, where implicit blocks 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: for block in ds:
b = Block.load( b = Block.load(
block, block,
play=play,
parent_block=parent_block, parent_block=parent_block,
role=role, role=role,
task_include=task_include, 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 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), Given a list of task datastructures (parsed from YAML),
return a list of Task() or TaskInclude() objects. 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: if 'block' in task:
t = Block.load( t = Block.load(
task, task,
play=play,
parent_block=block, parent_block=block,
role=role, role=role,
task_include=task_include, 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. 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. 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): def _load_pre_tasks(self, attr, ds):
''' '''
Loads a list of blocks from a list which may be mixed tasks/blocks. 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. 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): def _load_post_tasks(self, attr, ds):
''' '''
Loads a list of blocks from a list which may be mixed tasks/blocks. 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. 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): def _load_handlers(self, attr, ds):
''' '''
Loads a list of blocks from a list which may be mixed handlers/blocks. 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. 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): def _load_roles(self, attr, ds):
''' '''
@ -196,7 +196,7 @@ class Play(Base, Taggable, Become):
if len(self.roles) > 0: if len(self.roles) > 0:
for r in self.roles: for r in self.roles:
block_list.extend(r.compile()) block_list.extend(r.compile(play=self))
return block_list return block_list

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

@ -26,7 +26,7 @@ from ansible.template import Templar
class Taggable: class Taggable:
untagged = set(['untagged']) untagged = set(['untagged'])
_tags = FieldAttribute(isa='list', default=[]) _tags = FieldAttribute(isa='list', default=None)
def __init__(self): def __init__(self):
super(Taggable, self).__init__() super(Taggable, self).__init__()
@ -44,9 +44,11 @@ class Taggable:
Override for the 'tags' getattr fetcher, used from Base. Override for the 'tags' getattr fetcher, used from Base.
''' '''
tags = self._attributes['tags'] tags = self._attributes['tags']
if tags is None:
tags = []
if hasattr(self, '_get_parent_attribute'): if hasattr(self, '_get_parent_attribute'):
tags.extend(self._get_parent_attribute('tags')) tags = self._get_parent_attribute('tags', extend=True)
return list(set(tags)) return tags
def evaluate_tags(self, only_tags, skip_tags, all_vars): def evaluate_tags(self, only_tags, skip_tags, all_vars):
''' this checks if the current item should be executed depending on tag options ''' ''' 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'] del all_vars['when']
return all_vars 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): def copy(self, exclude_block=False):
new_me = super(Task, self).copy() new_me = super(Task, self).copy()
@ -299,12 +289,22 @@ class Task(Base, Conditional, Taggable, Become):
if self._task_include: if self._task_include:
self._task_include.set_loader(loader) 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. Generic logic to get the attribute or parent attribute for a task value.
''' '''
value = self._attributes[attr] value = self._attributes[attr]
if not value and self._block: if self._block and (not value or extend):
value = getattr(self._block, attr) 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 return value

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

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

Loading…
Cancel
Save