diff --git a/changelogs/fragments/implicit_flush_handlers_parents.yml b/changelogs/fragments/implicit_flush_handlers_parents.yml new file mode 100644 index 00000000000..ffff595b3c9 --- /dev/null +++ b/changelogs/fragments/implicit_flush_handlers_parents.yml @@ -0,0 +1,2 @@ +bugfixes: + - "Implicit ``meta: flush_handlers`` tasks now have a parent block to prevent potential tracebacks when calling methods like ``get_play()`` on them internally." diff --git a/lib/ansible/playbook/play.py b/lib/ansible/playbook/play.py index fed8074a875..831e0280214 100644 --- a/lib/ansible/playbook/play.py +++ b/lib/ansible/playbook/play.py @@ -298,7 +298,7 @@ class Play(Base, Taggable, CollectionSearch): # of the playbook execution flush_block = Block(play=self) - t = Task() + t = Task(block=flush_block) t.action = 'meta' t.resolved_action = 'ansible.builtin.meta' t.args['_raw_params'] = 'flush_handlers' @@ -318,6 +318,9 @@ class Play(Base, Taggable, CollectionSearch): else: flush_block.block = [t] + # NOTE keep flush_handlers tasks even if a section has no regular tasks, + # there may be notified handlers from the previous section + # (typically when a handler notifies a handler defined before) block_list = [] if self.force_handlers: noop_task = Task() @@ -327,18 +330,33 @@ class Play(Base, Taggable, CollectionSearch): noop_task.set_loader(self._loader) b = Block(play=self) - b.block = self.pre_tasks or [noop_task] + if self.pre_tasks: + b.block = self.pre_tasks + else: + nt = noop_task.copy(exclude_parent=True) + nt._parent = b + b.block = [nt] b.always = [flush_block] block_list.append(b) tasks = self._compile_roles() + self.tasks b = Block(play=self) - b.block = tasks or [noop_task] + if tasks: + b.block = tasks + else: + nt = noop_task.copy(exclude_parent=True) + nt._parent = b + b.block = [nt] b.always = [flush_block] block_list.append(b) b = Block(play=self) - b.block = self.post_tasks or [noop_task] + if self.post_tasks: + b.block = self.post_tasks + else: + nt = noop_task.copy(exclude_parent=True) + nt._parent = b + b.block = [nt] b.always = [flush_block] block_list.append(b)