mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Add play to the parent object structures for inheritence in v2
This commit is contained in:
parent
fb96173d10
commit
aafda44bb3
9 changed files with 98 additions and 44 deletions
|
@ -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…
Reference in a new issue