fixes to FA inheritance (#78990)

finalized applies to all field attributes
fix getting parent value
also remove unused/needed extend/prepend signature
moar testing
pull/79019/head^2
Brian Coca 3 years ago committed by GitHub
parent b5db71e318
commit ff6e4da36a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -479,24 +479,18 @@ class FieldAttributeBase:
return value
def set_to_context(self, name):
''' set to parent inherited value or Sentinel as appropriate'''
attribute = self.fattributes[name]
if isinstance(attribute, NonInheritableFieldAttribute):
self.set_to_default(name)
# setting to sentinel will trigger 'default/default()' on getter
setattr(self, name, Sentinel)
else:
try:
setattr(self, name, self._get_parent_attribute(name))
setattr(self, name, self._get_parent_attribute(name, omit=True))
except AttributeError:
# mostly playcontext as only tasks/handlers really resolve to parent
self.set_to_default(name)
def set_to_default(self, name):
attribute = self.fattributes[name]
if callable(attribute.default):
setattr(self, name, attribute.default())
else:
setattr(self, name, attribute.default)
# mostly playcontext as only tasks/handlers/blocks really resolve parent
setattr(self, name, Sentinel)
def post_validate(self, templar):
'''
@ -545,7 +539,6 @@ class FieldAttributeBase:
# or default specified in the FieldAttribute and move on
if omit_value is not None and value == omit_value:
self.set_to_context(name)
self._finalized = True
continue
# and make sure the attribute is of the type it should be

@ -294,14 +294,20 @@ class Block(Base, Conditional, CollectionSearch, Taggable):
for dep in dep_chain:
dep.set_loader(loader)
def _get_parent_attribute(self, attr, extend=False, prepend=False):
def _get_parent_attribute(self, attr, omit=False):
'''
Generic logic to get the attribute or parent attribute for a block value.
'''
extend = self.fattributes.get(attr).extend
prepend = self.fattributes.get(attr).prepend
try:
value = getattr(self, f'_{attr}', Sentinel)
# omit self, and only get parent values
if omit:
value = Sentinel
else:
value = getattr(self, f'_{attr}', Sentinel)
# If parent is static, we can grab attrs from the parent
# otherwise, defer to the grandparent
if getattr(self._parent, 'statically_loaded', True):

@ -457,14 +457,20 @@ class Task(Base, Conditional, Taggable, CollectionSearch):
if self._parent:
self._parent.set_loader(loader)
def _get_parent_attribute(self, attr, extend=False, prepend=False):
def _get_parent_attribute(self, attr, omit=False):
'''
Generic logic to get the attribute or parent attribute for a task value.
'''
extend = self.fattributes.get(attr).extend
prepend = self.fattributes.get(attr).prepend
try:
value = getattr(self, f'_{attr}', Sentinel)
# omit self, and only get parent values
if omit:
value = Sentinel
else:
value = getattr(self, f'_{attr}', Sentinel)
# If parent is static, we can grab attrs from the parent
# otherwise, defer to the grandparent
if getattr(self._parent, 'statically_loaded', True):

@ -0,0 +1,44 @@
- hosts: localhost
gather_facts: false
tasks:
- name: Make sure foo is gone
file:
path: foo
state: absent
- name: Create foo - should only be changed in first iteration
copy:
dest: foo
content: foo
check_mode: '{{ omit }}'
register: cmode
loop:
- 1
- 2
- when: ansible_check_mode
block:
- name: stat foo
stat: path=foo
register: foo
check_mode: off
- debug: var=foo
- name: validate expected outcomes when in check mode and file does not exist
assert:
that:
- cmode['results'][0] is changed
- cmode['results'][1] is changed
when: not foo['stat']['exists']
- name: validate expected outcomes when in check mode and file exists
assert:
that:
- cmode['results'][0] is not changed
- cmode['results'][1] is not changed
when: foo['stat']['exists']
- name: validate expected outcomes when not in check mode (file is always deleted)
assert:
that:
- cmode['results'][0] is changed
- cmode['results'][1] is not changed
when: not ansible_check_mode

@ -2,4 +2,10 @@
set -eux
# positive inheritance works
ANSIBLE_ROLES_PATH=../ ansible-playbook 48673.yml 75692.yml -i ../../inventory -v "$@"
# ensure negative also works
ansible-playbook -C C75692.yml -i ../../inventory -v "$@" # expects 'foo' not to exist
ansible-playbook C75692.yml -i ../../inventory -v "$@" # creates 'foo'
ansible-playbook -C C75692.yml -i ../../inventory -v "$@" # expects 'foo' does exist

Loading…
Cancel
Save