From 3fd0e12571952edd0eb83d42da506b028802197f Mon Sep 17 00:00:00 2001 From: Martin Krizek Date: Thu, 23 Feb 2023 20:32:22 +0100 Subject: [PATCH] Introduce Delegatable and Notifiable mixin classes (#80077) * Introduce Delegatable and Notifiable mixin classes * fix sanity * fix sanity --- changelogs/fragments/new-mixins.yml | 2 ++ lib/ansible/playbook/block.py | 11 ++++------- lib/ansible/playbook/delegatable.py | 10 ++++++++++ lib/ansible/playbook/notifiable.py | 9 +++++++++ lib/ansible/playbook/role/__init__.py | 6 ++---- lib/ansible/playbook/role/include.py | 7 ++----- lib/ansible/playbook/task.py | 9 ++++----- 7 files changed, 33 insertions(+), 21 deletions(-) create mode 100644 changelogs/fragments/new-mixins.yml create mode 100644 lib/ansible/playbook/delegatable.py create mode 100644 lib/ansible/playbook/notifiable.py diff --git a/changelogs/fragments/new-mixins.yml b/changelogs/fragments/new-mixins.yml new file mode 100644 index 00000000000..37271c19afe --- /dev/null +++ b/changelogs/fragments/new-mixins.yml @@ -0,0 +1,2 @@ +minor_changes: + - Introduce ``Delegatable`` and ``Notifiable`` mixin classes for playbook objects diff --git a/lib/ansible/playbook/block.py b/lib/ansible/playbook/block.py index fabaf7f7688..109b3aa37c3 100644 --- a/lib/ansible/playbook/block.py +++ b/lib/ansible/playbook/block.py @@ -21,28 +21,25 @@ __metaclass__ = type import ansible.constants as C from ansible.errors import AnsibleParserError -from ansible.playbook.attribute import FieldAttribute, NonInheritableFieldAttribute +from ansible.playbook.attribute import NonInheritableFieldAttribute from ansible.playbook.base import Base from ansible.playbook.conditional import Conditional from ansible.playbook.collectionsearch import CollectionSearch +from ansible.playbook.delegatable import Delegatable from ansible.playbook.helpers import load_list_of_tasks +from ansible.playbook.notifiable import Notifiable from ansible.playbook.role import Role from ansible.playbook.taggable import Taggable from ansible.utils.sentinel import Sentinel -class Block(Base, Conditional, CollectionSearch, Taggable): +class Block(Base, Conditional, CollectionSearch, Taggable, Notifiable, Delegatable): # main block fields containing the task lists block = NonInheritableFieldAttribute(isa='list', default=list) rescue = NonInheritableFieldAttribute(isa='list', default=list) always = NonInheritableFieldAttribute(isa='list', default=list) - # other fields for task compat - notify = FieldAttribute(isa='list') - delegate_to = FieldAttribute(isa='string') - delegate_facts = FieldAttribute(isa='bool') - # for future consideration? this would be functionally # similar to the 'else' clause for exceptions # otherwise = FieldAttribute(isa='list') diff --git a/lib/ansible/playbook/delegatable.py b/lib/ansible/playbook/delegatable.py new file mode 100644 index 00000000000..8a5df1e7a5c --- /dev/null +++ b/lib/ansible/playbook/delegatable.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright The Ansible project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from ansible.playbook.attribute import FieldAttribute + + +class Delegatable: + delegate_to = FieldAttribute(isa='string') + delegate_facts = FieldAttribute(isa='bool') diff --git a/lib/ansible/playbook/notifiable.py b/lib/ansible/playbook/notifiable.py new file mode 100644 index 00000000000..a183293d564 --- /dev/null +++ b/lib/ansible/playbook/notifiable.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright The Ansible project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from ansible.playbook.attribute import FieldAttribute + + +class Notifiable: + notify = FieldAttribute(isa='list') diff --git a/lib/ansible/playbook/role/__init__.py b/lib/ansible/playbook/role/__init__.py index b154ca30a37..b35519e4ca3 100644 --- a/lib/ansible/playbook/role/__init__.py +++ b/lib/ansible/playbook/role/__init__.py @@ -32,6 +32,7 @@ from ansible.playbook.attribute import FieldAttribute from ansible.playbook.base import Base from ansible.playbook.collectionsearch import CollectionSearch from ansible.playbook.conditional import Conditional +from ansible.playbook.delegatable import Delegatable from ansible.playbook.helpers import load_list_of_blocks from ansible.playbook.role.metadata import RoleMetadata from ansible.playbook.taggable import Taggable @@ -97,10 +98,7 @@ def hash_params(params): return frozenset((params,)) -class Role(Base, Conditional, Taggable, CollectionSearch): - - delegate_to = FieldAttribute(isa='string') - delegate_facts = FieldAttribute(isa='bool') +class Role(Base, Conditional, Taggable, CollectionSearch, Delegatable): def __init__(self, play=None, from_files=None, from_include=False, validate=True, public=True): self._role_name = None diff --git a/lib/ansible/playbook/role/include.py b/lib/ansible/playbook/role/include.py index e0d4b67b14d..91f405162a5 100644 --- a/lib/ansible/playbook/role/include.py +++ b/lib/ansible/playbook/role/include.py @@ -22,7 +22,7 @@ __metaclass__ = type from ansible.errors import AnsibleError, AnsibleParserError from ansible.module_utils.six import string_types from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject -from ansible.playbook.attribute import FieldAttribute +from ansible.playbook.delegatable import Delegatable from ansible.playbook.role.definition import RoleDefinition from ansible.module_utils._text import to_native @@ -30,16 +30,13 @@ from ansible.module_utils._text import to_native __all__ = ['RoleInclude'] -class RoleInclude(RoleDefinition): +class RoleInclude(RoleDefinition, Delegatable): """ A derivative of RoleDefinition, used by playbook code when a role is included for execution in a play. """ - delegate_to = FieldAttribute(isa='string') - delegate_facts = FieldAttribute(isa='bool', default=False) - def __init__(self, play=None, role_basedir=None, variable_manager=None, loader=None, collection_list=None): super(RoleInclude, self).__init__(play=play, role_basedir=role_basedir, variable_manager=variable_manager, loader=loader, collection_list=collection_list) diff --git a/lib/ansible/playbook/task.py b/lib/ansible/playbook/task.py index c405535e93c..f6b6caf1883 100644 --- a/lib/ansible/playbook/task.py +++ b/lib/ansible/playbook/task.py @@ -26,12 +26,14 @@ from ansible.module_utils.six import string_types from ansible.parsing.mod_args import ModuleArgsParser from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject, AnsibleMapping from ansible.plugins.loader import lookup_loader -from ansible.playbook.attribute import FieldAttribute, NonInheritableFieldAttribute +from ansible.playbook.attribute import NonInheritableFieldAttribute from ansible.playbook.base import Base from ansible.playbook.block import Block from ansible.playbook.collectionsearch import CollectionSearch from ansible.playbook.conditional import Conditional +from ansible.playbook.delegatable import Delegatable from ansible.playbook.loop_control import LoopControl +from ansible.playbook.notifiable import Notifiable from ansible.playbook.role import Role from ansible.playbook.taggable import Taggable from ansible.utils.collection_loader import AnsibleCollectionConfig @@ -43,7 +45,7 @@ __all__ = ['Task'] display = Display() -class Task(Base, Conditional, Taggable, CollectionSearch): +class Task(Base, Conditional, Taggable, CollectionSearch, Notifiable, Delegatable): """ A task is a language feature that represents a call to a module, with given arguments and other parameters. @@ -72,12 +74,9 @@ class Task(Base, Conditional, Taggable, CollectionSearch): async_val = NonInheritableFieldAttribute(isa='int', default=0, alias='async') changed_when = NonInheritableFieldAttribute(isa='list', default=list) delay = NonInheritableFieldAttribute(isa='int', default=5) - delegate_to = FieldAttribute(isa='string') - delegate_facts = FieldAttribute(isa='bool') failed_when = NonInheritableFieldAttribute(isa='list', default=list) loop = NonInheritableFieldAttribute() loop_control = NonInheritableFieldAttribute(isa='class', class_type=LoopControl, default=LoopControl) - notify = FieldAttribute(isa='list') poll = NonInheritableFieldAttribute(isa='int', default=C.DEFAULT_POLL_INTERVAL) register = NonInheritableFieldAttribute(isa='string', static=True) retries = NonInheritableFieldAttribute(isa='int', default=3)