Use FAs with inheritance only when applicable (#80026)

... and set default value of an attribute on an object
only in NonInheritableFA.

Fixes #79777

ci_complete
pull/80073/head
Martin Krizek 2 years ago committed by GitHub
parent ed879954f9
commit 6c3d2a4e51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,2 @@
bugfixes:
- "Fix an issue where the value of ``become`` was ignored when used on a role used as a dependency in ``main/meta.yml`` (https://github.com/ansible/ansible/issues/79777)"

@ -176,7 +176,6 @@ class FieldAttribute(Attribute):
value = self.default value = self.default
if callable(value): if callable(value):
value = value() value = value()
setattr(obj, f'_{self.name}', value)
return value return value

@ -19,14 +19,14 @@
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
from ansible.playbook.attribute import FieldAttribute from ansible.playbook.attribute import NonInheritableFieldAttribute
from ansible.playbook.task import Task from ansible.playbook.task import Task
from ansible.module_utils.six import string_types from ansible.module_utils.six import string_types
class Handler(Task): class Handler(Task):
listen = FieldAttribute(isa='list', default=list, listof=string_types, static=True) listen = NonInheritableFieldAttribute(isa='list', default=list, listof=string_types, static=True)
def __init__(self, block=None, role=None, task_include=None): def __init__(self, block=None, role=None, task_include=None):
self.notified_hosts = [] self.notified_hosts = []

@ -19,18 +19,18 @@
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
from ansible.playbook.attribute import FieldAttribute from ansible.playbook.attribute import NonInheritableFieldAttribute
from ansible.playbook.base import FieldAttributeBase from ansible.playbook.base import FieldAttributeBase
class LoopControl(FieldAttributeBase): class LoopControl(FieldAttributeBase):
loop_var = FieldAttribute(isa='str', default='item', always_post_validate=True) loop_var = NonInheritableFieldAttribute(isa='str', default='item', always_post_validate=True)
index_var = FieldAttribute(isa='str', always_post_validate=True) index_var = NonInheritableFieldAttribute(isa='str', always_post_validate=True)
label = FieldAttribute(isa='str') label = NonInheritableFieldAttribute(isa='str')
pause = FieldAttribute(isa='float', default=0, always_post_validate=True) pause = NonInheritableFieldAttribute(isa='float', default=0, always_post_validate=True)
extended = FieldAttribute(isa='bool', always_post_validate=True) extended = NonInheritableFieldAttribute(isa='bool', always_post_validate=True)
extended_allitems = FieldAttribute(isa='bool', default=True, always_post_validate=True) extended_allitems = NonInheritableFieldAttribute(isa='bool', default=True, always_post_validate=True)
def __init__(self): def __init__(self):
super(LoopControl, self).__init__() super(LoopControl, self).__init__()

@ -25,7 +25,7 @@ from ansible.errors import AnsibleParserError, AnsibleAssertionError
from ansible.module_utils._text import to_native from ansible.module_utils._text import to_native
from ansible.module_utils.common.collections import is_sequence from ansible.module_utils.common.collections import is_sequence
from ansible.module_utils.six import binary_type, string_types, text_type from ansible.module_utils.six import binary_type, string_types, text_type
from ansible.playbook.attribute import FieldAttribute from ansible.playbook.attribute import NonInheritableFieldAttribute
from ansible.playbook.base import Base from ansible.playbook.base import Base
from ansible.playbook.block import Block from ansible.playbook.block import Block
from ansible.playbook.collectionsearch import CollectionSearch from ansible.playbook.collectionsearch import CollectionSearch
@ -55,35 +55,35 @@ class Play(Base, Taggable, CollectionSearch):
""" """
# ================================================================================= # =================================================================================
hosts = FieldAttribute(isa='list', required=True, listof=string_types, always_post_validate=True, priority=-2) hosts = NonInheritableFieldAttribute(isa='list', required=True, listof=string_types, always_post_validate=True, priority=-2)
# Facts # Facts
gather_facts = FieldAttribute(isa='bool', default=None, always_post_validate=True) gather_facts = NonInheritableFieldAttribute(isa='bool', default=None, always_post_validate=True)
# defaults to be deprecated, should be 'None' in future # defaults to be deprecated, should be 'None' in future
gather_subset = FieldAttribute(isa='list', default=(lambda: C.DEFAULT_GATHER_SUBSET), listof=string_types, always_post_validate=True) gather_subset = NonInheritableFieldAttribute(isa='list', default=(lambda: C.DEFAULT_GATHER_SUBSET), listof=string_types, always_post_validate=True)
gather_timeout = FieldAttribute(isa='int', default=C.DEFAULT_GATHER_TIMEOUT, always_post_validate=True) gather_timeout = NonInheritableFieldAttribute(isa='int', default=C.DEFAULT_GATHER_TIMEOUT, always_post_validate=True)
fact_path = FieldAttribute(isa='string', default=C.DEFAULT_FACT_PATH) fact_path = NonInheritableFieldAttribute(isa='string', default=C.DEFAULT_FACT_PATH)
# Variable Attributes # Variable Attributes
vars_files = FieldAttribute(isa='list', default=list, priority=99) vars_files = NonInheritableFieldAttribute(isa='list', default=list, priority=99)
vars_prompt = FieldAttribute(isa='list', default=list, always_post_validate=False) vars_prompt = NonInheritableFieldAttribute(isa='list', default=list, always_post_validate=False)
# Role Attributes # Role Attributes
roles = FieldAttribute(isa='list', default=list, priority=90) roles = NonInheritableFieldAttribute(isa='list', default=list, priority=90)
# Block (Task) Lists Attributes # Block (Task) Lists Attributes
handlers = FieldAttribute(isa='list', default=list, priority=-1) handlers = NonInheritableFieldAttribute(isa='list', default=list, priority=-1)
pre_tasks = FieldAttribute(isa='list', default=list, priority=-1) pre_tasks = NonInheritableFieldAttribute(isa='list', default=list, priority=-1)
post_tasks = FieldAttribute(isa='list', default=list, priority=-1) post_tasks = NonInheritableFieldAttribute(isa='list', default=list, priority=-1)
tasks = FieldAttribute(isa='list', default=list, priority=-1) tasks = NonInheritableFieldAttribute(isa='list', default=list, priority=-1)
# Flag/Setting Attributes # Flag/Setting Attributes
force_handlers = FieldAttribute(isa='bool', default=context.cliargs_deferred_get('force_handlers'), always_post_validate=True) force_handlers = NonInheritableFieldAttribute(isa='bool', default=context.cliargs_deferred_get('force_handlers'), always_post_validate=True)
max_fail_percentage = FieldAttribute(isa='percent', always_post_validate=True) max_fail_percentage = NonInheritableFieldAttribute(isa='percent', always_post_validate=True)
serial = FieldAttribute(isa='list', default=list, always_post_validate=True) serial = NonInheritableFieldAttribute(isa='list', default=list, always_post_validate=True)
strategy = FieldAttribute(isa='string', default=C.DEFAULT_STRATEGY, always_post_validate=True) strategy = NonInheritableFieldAttribute(isa='string', default=C.DEFAULT_STRATEGY, always_post_validate=True)
order = FieldAttribute(isa='string', always_post_validate=True) order = NonInheritableFieldAttribute(isa='string', always_post_validate=True)
# ================================================================================= # =================================================================================

@ -27,7 +27,7 @@ from ansible.module_utils._text import to_bytes
from ansible.module_utils.six import string_types from ansible.module_utils.six import string_types
from ansible.parsing.splitter import split_args from ansible.parsing.splitter import split_args
from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject, AnsibleMapping from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject, AnsibleMapping
from ansible.playbook.attribute import FieldAttribute from ansible.playbook.attribute import NonInheritableFieldAttribute
from ansible.playbook.base import Base from ansible.playbook.base import Base
from ansible.playbook.conditional import Conditional from ansible.playbook.conditional import Conditional
from ansible.playbook.taggable import Taggable from ansible.playbook.taggable import Taggable
@ -41,8 +41,8 @@ display = Display()
class PlaybookInclude(Base, Conditional, Taggable): class PlaybookInclude(Base, Conditional, Taggable):
import_playbook = FieldAttribute(isa='string') import_playbook = NonInheritableFieldAttribute(isa='string')
vars_val = FieldAttribute(isa='dict', default=dict, alias='vars') vars_val = NonInheritableFieldAttribute(isa='dict', default=dict, alias='vars')
@staticmethod @staticmethod
def load(data, basedir, variable_manager=None, loader=None): def load(data, basedir, variable_manager=None, loader=None):

@ -25,7 +25,7 @@ from ansible import constants as C
from ansible.errors import AnsibleError, AnsibleAssertionError from ansible.errors import AnsibleError, AnsibleAssertionError
from ansible.module_utils.six import string_types from ansible.module_utils.six import string_types
from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject, AnsibleMapping from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject, AnsibleMapping
from ansible.playbook.attribute import FieldAttribute from ansible.playbook.attribute import NonInheritableFieldAttribute
from ansible.playbook.base import Base from ansible.playbook.base import Base
from ansible.playbook.collectionsearch import CollectionSearch from ansible.playbook.collectionsearch import CollectionSearch
from ansible.playbook.conditional import Conditional from ansible.playbook.conditional import Conditional
@ -43,7 +43,7 @@ display = Display()
class RoleDefinition(Base, Conditional, Taggable, CollectionSearch): class RoleDefinition(Base, Conditional, Taggable, CollectionSearch):
role = FieldAttribute(isa='string') role = NonInheritableFieldAttribute(isa='string')
def __init__(self, play=None, role_basedir=None, variable_manager=None, loader=None, collection_list=None): def __init__(self, play=None, role_basedir=None, variable_manager=None, loader=None, collection_list=None):

@ -24,7 +24,7 @@ import os
from ansible.errors import AnsibleParserError, AnsibleError from ansible.errors import AnsibleParserError, AnsibleError
from ansible.module_utils._text import to_native from ansible.module_utils._text import to_native
from ansible.module_utils.six import string_types from ansible.module_utils.six import string_types
from ansible.playbook.attribute import FieldAttribute from ansible.playbook.attribute import NonInheritableFieldAttribute
from ansible.playbook.base import Base from ansible.playbook.base import Base
from ansible.playbook.collectionsearch import CollectionSearch from ansible.playbook.collectionsearch import CollectionSearch
from ansible.playbook.helpers import load_list_of_roles from ansible.playbook.helpers import load_list_of_roles
@ -39,10 +39,10 @@ class RoleMetadata(Base, CollectionSearch):
within each Role (meta/main.yml). within each Role (meta/main.yml).
''' '''
allow_duplicates = FieldAttribute(isa='bool', default=False) allow_duplicates = NonInheritableFieldAttribute(isa='bool', default=False)
dependencies = FieldAttribute(isa='list', default=list) dependencies = NonInheritableFieldAttribute(isa='list', default=list)
galaxy_info = FieldAttribute(isa='GalaxyInfo') galaxy_info = NonInheritableFieldAttribute(isa='GalaxyInfo')
argument_specs = FieldAttribute(isa='dict', default=dict) argument_specs = NonInheritableFieldAttribute(isa='dict', default=dict)
def __init__(self, owner=None): def __init__(self, owner=None):
self._owner = owner self._owner = owner

@ -22,7 +22,7 @@ from os.path import basename
import ansible.constants as C import ansible.constants as C
from ansible.errors import AnsibleParserError from ansible.errors import AnsibleParserError
from ansible.playbook.attribute import FieldAttribute from ansible.playbook.attribute import NonInheritableFieldAttribute
from ansible.playbook.task_include import TaskInclude from ansible.playbook.task_include import TaskInclude
from ansible.playbook.role import Role from ansible.playbook.role import Role
from ansible.playbook.role.include import RoleInclude from ansible.playbook.role.include import RoleInclude
@ -51,9 +51,9 @@ class IncludeRole(TaskInclude):
# ATTRIBUTES # ATTRIBUTES
# private as this is a 'module options' vs a task property # private as this is a 'module options' vs a task property
allow_duplicates = FieldAttribute(isa='bool', default=True, private=True) allow_duplicates = NonInheritableFieldAttribute(isa='bool', default=True, private=True)
public = FieldAttribute(isa='bool', default=False, private=True) public = NonInheritableFieldAttribute(isa='bool', default=False, private=True)
rolespec_validate = FieldAttribute(isa='bool', default=True) rolespec_validate = NonInheritableFieldAttribute(isa='bool', default=True)
def __init__(self, block=None, role=None, task_include=None): def __init__(self, block=None, role=None, task_include=None):

@ -66,22 +66,22 @@ class Task(Base, Conditional, Taggable, CollectionSearch):
# inheritance is only triggered if the 'current value' is Sentinel, # inheritance is only triggered if the 'current value' is Sentinel,
# default can be set at play/top level object and inheritance will take it's course. # default can be set at play/top level object and inheritance will take it's course.
args = FieldAttribute(isa='dict', default=dict) args = NonInheritableFieldAttribute(isa='dict', default=dict)
action = FieldAttribute(isa='string') action = NonInheritableFieldAttribute(isa='string')
async_val = FieldAttribute(isa='int', default=0, alias='async') async_val = NonInheritableFieldAttribute(isa='int', default=0, alias='async')
changed_when = FieldAttribute(isa='list', default=list) changed_when = NonInheritableFieldAttribute(isa='list', default=list)
delay = FieldAttribute(isa='int', default=5) delay = NonInheritableFieldAttribute(isa='int', default=5)
delegate_to = FieldAttribute(isa='string') delegate_to = FieldAttribute(isa='string')
delegate_facts = FieldAttribute(isa='bool') delegate_facts = FieldAttribute(isa='bool')
failed_when = FieldAttribute(isa='list', default=list) failed_when = NonInheritableFieldAttribute(isa='list', default=list)
loop = FieldAttribute() loop = NonInheritableFieldAttribute()
loop_control = NonInheritableFieldAttribute(isa='class', class_type=LoopControl, default=LoopControl) loop_control = NonInheritableFieldAttribute(isa='class', class_type=LoopControl, default=LoopControl)
notify = FieldAttribute(isa='list') notify = FieldAttribute(isa='list')
poll = FieldAttribute(isa='int', default=C.DEFAULT_POLL_INTERVAL) poll = NonInheritableFieldAttribute(isa='int', default=C.DEFAULT_POLL_INTERVAL)
register = FieldAttribute(isa='string', static=True) register = NonInheritableFieldAttribute(isa='string', static=True)
retries = FieldAttribute(isa='int', default=3) retries = NonInheritableFieldAttribute(isa='int', default=3)
until = FieldAttribute(isa='list', default=list) until = NonInheritableFieldAttribute(isa='list', default=list)
# deprecated, used to be loop and loop_args but loop has been repurposed # deprecated, used to be loop and loop_args but loop has been repurposed
loop_with = NonInheritableFieldAttribute(isa='string', private=True) loop_with = NonInheritableFieldAttribute(isa='string', private=True)

@ -0,0 +1,8 @@
- hosts: localhost
gather_facts: false
tasks:
- include_role:
name: "{{ item }}"
loop:
- setup_test_user
- role-meta-inheritance

@ -0,0 +1,4 @@
dependencies:
- role: whoami
become: true
become_user: ansibletest0

@ -3,3 +3,5 @@
set -eux set -eux
ANSIBLE_ROLES_PATH=../ ansible-playbook -i ../../inventory test.yml "$@" ANSIBLE_ROLES_PATH=../ ansible-playbook -i ../../inventory test.yml "$@"
ANSIBLE_ROLES_PATH=../ ansible-playbook -i ../../inventory dep_keyword_inheritance.yml "$@"

Loading…
Cancel
Save