Skip self._parent on dynamic, defer to grandparent for attr lookup (#38827)
* Skip self._parent on dynamic, defer to grandparent for attr lookup * Revert _inheritable * Add tests for include inheritance from static blocks Fixes #38037 #36194
This commit is contained in:
parent
1d5c933ecf
commit
354aa8d602
11 changed files with 63 additions and 16 deletions
|
@ -174,8 +174,6 @@ class Base(with_metaclass(BaseMeta, object)):
|
||||||
'su', 'su_user', 'su_pass', 'su_exe', 'su_flags',
|
'su', 'su_user', 'su_pass', 'su_exe', 'su_flags',
|
||||||
]
|
]
|
||||||
|
|
||||||
_inheritable = True
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
# initialize the data loader and variable manager, which will be provided
|
# initialize the data loader and variable manager, which will be provided
|
||||||
|
|
|
@ -298,13 +298,20 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
prepend = self._valid_attrs[attr].prepend
|
prepend = self._valid_attrs[attr].prepend
|
||||||
try:
|
try:
|
||||||
value = self._attributes[attr]
|
value = self._attributes[attr]
|
||||||
if self._parent and (value is None or extend):
|
# If parent is static, we can grab attrs from the parent
|
||||||
|
# otherwise, defer to the grandparent
|
||||||
|
if getattr(self._parent, 'statically_loaded', True):
|
||||||
|
_parent = self._parent
|
||||||
|
else:
|
||||||
|
_parent = self._parent._parent
|
||||||
|
|
||||||
|
if _parent and (value is None or extend):
|
||||||
try:
|
try:
|
||||||
if getattr(self._parent, 'statically_loaded', True):
|
if getattr(_parent, 'statically_loaded', True):
|
||||||
if hasattr(self._parent, '_get_parent_attribute'):
|
if hasattr(_parent, '_get_parent_attribute'):
|
||||||
parent_value = self._parent._get_parent_attribute(attr)
|
parent_value = _parent._get_parent_attribute(attr)
|
||||||
else:
|
else:
|
||||||
parent_value = self._parent._attributes.get(attr, None)
|
parent_value = _parent._attributes.get(attr, None)
|
||||||
if extend:
|
if extend:
|
||||||
value = self._extend_value(value, parent_value, prepend)
|
value = self._extend_value(value, parent_value, prepend)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -48,8 +48,6 @@ class IncludeRole(TaskInclude):
|
||||||
OTHER_ARGS = ('private', 'allow_duplicates') # assigned to matching property
|
OTHER_ARGS = ('private', 'allow_duplicates') # assigned to matching property
|
||||||
VALID_ARGS = tuple(frozenset(BASE + FROM_ARGS + OTHER_ARGS)) # all valid args
|
VALID_ARGS = tuple(frozenset(BASE + FROM_ARGS + OTHER_ARGS)) # all valid args
|
||||||
|
|
||||||
_inheritable = False
|
|
||||||
|
|
||||||
# =================================================================================
|
# =================================================================================
|
||||||
# ATTRIBUTES
|
# ATTRIBUTES
|
||||||
|
|
||||||
|
|
|
@ -423,13 +423,20 @@ class Task(Base, Conditional, Taggable, Become):
|
||||||
prepend = self._valid_attrs[attr].prepend
|
prepend = self._valid_attrs[attr].prepend
|
||||||
try:
|
try:
|
||||||
value = self._attributes[attr]
|
value = self._attributes[attr]
|
||||||
if self._parent and (value is None or extend):
|
# If parent is static, we can grab attrs from the parent
|
||||||
if getattr(self._parent, 'statically_loaded', True):
|
# otherwise, defer to the grandparent
|
||||||
|
if getattr(self._parent, 'statically_loaded', True):
|
||||||
|
_parent = self._parent
|
||||||
|
else:
|
||||||
|
_parent = self._parent._parent
|
||||||
|
|
||||||
|
if _parent and (value is None or extend):
|
||||||
|
if getattr(_parent, 'statically_loaded', True):
|
||||||
# vars are always inheritable, other attributes might not be for the partent but still should be for other ancestors
|
# vars are always inheritable, other attributes might not be for the partent but still should be for other ancestors
|
||||||
if attr != 'vars' and getattr(self._parent, '_inheritable', True) and hasattr(self._parent, '_get_parent_attribute'):
|
if attr != 'vars' and hasattr(_parent, '_get_parent_attribute'):
|
||||||
parent_value = self._parent._get_parent_attribute(attr)
|
parent_value = _parent._get_parent_attribute(attr)
|
||||||
else:
|
else:
|
||||||
parent_value = self._parent._attributes.get(attr, None)
|
parent_value = _parent._attributes.get(attr, None)
|
||||||
|
|
||||||
if extend:
|
if extend:
|
||||||
value = self._extend_value(value, parent_value, prepend)
|
value = self._extend_value(value, parent_value, prepend)
|
||||||
|
|
|
@ -50,8 +50,6 @@ class TaskInclude(Task):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load(data, block=None, role=None, task_include=None, variable_manager=None, loader=None):
|
def load(data, block=None, role=None, task_include=None, variable_manager=None, loader=None):
|
||||||
t = TaskInclude(block=block, role=role, task_include=task_include)
|
t = TaskInclude(block=block, role=role, task_include=task_include)
|
||||||
if t.action == 'include_task':
|
|
||||||
t._inheritable = False
|
|
||||||
return t.load_data(data, variable_manager=variable_manager, loader=loader)
|
return t.load_data(data, variable_manager=variable_manager, loader=loader)
|
||||||
|
|
||||||
def copy(self, exclude_parent=False, exclude_tasks=False):
|
def copy(self, exclude_parent=False, exclude_tasks=False):
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
- command: "true"
|
||||||
|
register: block_include_result
|
|
@ -0,0 +1 @@
|
||||||
|
- include_tasks: include_level_1.yml
|
|
@ -0,0 +1,2 @@
|
||||||
|
- command: "true"
|
||||||
|
register: import_include_include_result
|
|
@ -0,0 +1 @@
|
||||||
|
- include_tasks: import_include_include_tasks.yml
|
|
@ -55,3 +55,7 @@ gen_task_files
|
||||||
ANSIBLE_STRATEGY='linear' ansible-playbook test_copious_include_tasks.yml -i ../../inventory "$@" --skip-tags never
|
ANSIBLE_STRATEGY='linear' ansible-playbook test_copious_include_tasks.yml -i ../../inventory "$@" --skip-tags never
|
||||||
ANSIBLE_STRATEGY='free' ansible-playbook test_copious_include_tasks.yml -i ../../inventory "$@" --skip-tags never
|
ANSIBLE_STRATEGY='free' ansible-playbook test_copious_include_tasks.yml -i ../../inventory "$@" --skip-tags never
|
||||||
rm -f tasks/hello/*.yml
|
rm -f tasks/hello/*.yml
|
||||||
|
|
||||||
|
# Inlcuded tasks should inherit attrs from non-dynamic blocks in parent chain
|
||||||
|
# https://github.com/ansible/ansible/pull/38827
|
||||||
|
ANSIBLE_STRATEGY='linear' ansible-playbook test_grandparent_inheritance.yml -i ../../inventory "$@"
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
---
|
||||||
|
- hosts: testhost
|
||||||
|
gather_facts: false
|
||||||
|
tasks:
|
||||||
|
- debug:
|
||||||
|
var: inventory_hostname
|
||||||
|
|
||||||
|
- name: Test included tasks inherit from block
|
||||||
|
check_mode: true
|
||||||
|
block:
|
||||||
|
- include_tasks: grandchild/block_include_tasks.yml
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
var: block_include_result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- block_include_result is skipped
|
||||||
|
|
||||||
|
- name: Test included tasks inherit deeply from import
|
||||||
|
import_tasks: grandchild/import.yml
|
||||||
|
check_mode: true
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
var: import_include_include_result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- import_include_include_result is skipped
|
Loading…
Reference in a new issue