diff --git a/.github/BOTMETA.yml b/.github/BOTMETA.yml index 100dddae63..50a92dabb3 100644 --- a/.github/BOTMETA.yml +++ b/.github/BOTMETA.yml @@ -77,6 +77,8 @@ files: $callbacks/opentelemetry.py: keywords: opentelemetry observability maintainers: v1v + $callbacks/print_task.py: + maintainers: demonpig $callbacks/say.py: keywords: brew cask darwin homebrew macosx macports osx labels: macos say diff --git a/plugins/callback/print_task.py b/plugins/callback/print_task.py new file mode 100644 index 0000000000..7407b0e803 --- /dev/null +++ b/plugins/callback/print_task.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2025, Max Mitschke +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = r''' +name: print_task +type: aggregate +short_description: Prints playbook task snippet to job output +description: + - This plugin prints the currently executing playbook task to the job output. +version_added: 10.7.0 +requirements: + - enable in configuration +''' + +EXAMPLES = r''' +ansible.cfg: > + # Enable plugin + [defaults] + callbacks_enabled=community.general.print_task +''' + +from yaml import load, dump + +try: + from yaml import CSafeDumper as SafeDumper + from yaml import CSafeLoader as SafeLoader +except ImportError: + from yaml import SafeDumper, SafeLoader + +from ansible.plugins.callback import CallbackBase + + +class CallbackModule(CallbackBase): + """ + This callback module tells you how long your plays ran for. + """ + CALLBACK_VERSION = 2.0 + CALLBACK_TYPE = 'aggregate' + CALLBACK_NAME = 'community.general.print_task' + + CALLBACK_NEEDS_ENABLED = True + + def __init__(self): + super(CallbackModule, self).__init__() + self._printed_message = False + + def _print_task(self, task): + if hasattr(task, '_ds'): + task_snippet = load(str([task._ds.copy()]), Loader=SafeLoader) + task_yaml = dump(task_snippet, sort_keys=False, Dumper=SafeDumper) + self._display.display(f"\n{task_yaml}\n") + self._printed_message = True + + def v2_playbook_on_task_start(self, task, is_conditional): + self._printed_message = False + + def v2_runner_on_start(self, host, task): + if not self._printed_message: + self._print_task(task) diff --git a/tests/integration/targets/callback_print_task/aliases b/tests/integration/targets/callback_print_task/aliases new file mode 100644 index 0000000000..3e2dd244c1 --- /dev/null +++ b/tests/integration/targets/callback_print_task/aliases @@ -0,0 +1,6 @@ +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +azp/posix/3 +needs/target/callback diff --git a/tests/integration/targets/callback_print_task/tasks/main.yml b/tests/integration/targets/callback_print_task/tasks/main.yml new file mode 100644 index 0000000000..718ba607a7 --- /dev/null +++ b/tests/integration/targets/callback_print_task/tasks/main.yml @@ -0,0 +1,132 @@ +--- +#################################################################### +# WARNING: These are designed specifically for Ansible tests # +# and should not be used as examples of how to write Ansible roles # +#################################################################### + +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +- name: Run tests + include_role: + name: callback + vars: + tests: + - name: community.general.print_task is not enabled + environment: + ANSIBLE_NOCOLOR: 'true' + ANSIBLE_FORCE_COLOR: 'false' + playbook: | + - hosts: testhost + gather_facts: false + tasks: + - name: Sample task + debug: + msg: This is a test + expected_output: [ + "", + "PLAY [testhost] ****************************************************************", + "", + "TASK [Sample task] *************************************************************", + "ok: [testhost] => {", + " \"msg\": \"This is a test\"", + "}", + "", + "PLAY RECAP *********************************************************************", + "testhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 " + ] + + - name: community.general.print_task is enabled + environment: + ANSIBLE_NOCOLOR: 'true' + ANSIBLE_FORCE_COLOR: 'false' + ANSIBLE_CALLBACKS_ENABLED: 'community.general.print_task' + playbook: | + - hosts: testhost + gather_facts: false + tasks: + - name: Sample task + debug: + msg: This is a test + expected_output: [ + "", + "PLAY [testhost] ****************************************************************", + "", + "TASK [Sample task] *************************************************************", + "", + "- name: Sample task", + " debug:", + " msg: This is a test", + "", + "ok: [testhost] => {", + " \"msg\": \"This is a test\"", + "}", + "", + "PLAY RECAP *********************************************************************", + "testhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 " + ] + + - name: Print with msg parameter on the same line + environment: + ANSIBLE_NOCOLOR: 'true' + ANSIBLE_FORCE_COLOR: 'false' + ANSIBLE_CALLBACKS_ENABLED: 'community.general.print_task' + playbook: | + - hosts: testhost + gather_facts: false + tasks: + - name: Sample task + debug: msg="This is a test" + expected_output: [ + "", + "PLAY [testhost] ****************************************************************", + "", + "TASK [Sample task] *************************************************************", + "", + "- name: Sample task", + " debug: msg=\"This is a test\"", + "", + "ok: [testhost] => {", + " \"msg\": \"This is a test\"", + "}", + "", + "PLAY RECAP *********************************************************************", + "testhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 " + ] + + - name: Task with additional parameters + environment: + ANSIBLE_NOCOLOR: 'true' + ANSIBLE_FORCE_COLOR: 'false' + ANSIBLE_CALLBACKS_ENABLED: 'community.general.print_task' + playbook: | + - hosts: testhost + gather_facts: false + tasks: + - name: Sample task + when: True + vars: + test_var: "Hello World" + debug: + var: test_var + expected_output: [ + "", + "PLAY [testhost] ****************************************************************", + "", + "TASK [Sample task] *************************************************************", + "", + "- name: Sample task", + " when: true", + " vars:", + " test_var: Hello World", + " debug:", + " var: test_var", + "", + "ok: [testhost] => {", + " \"test_var\": \"Hello World\"", + "}", + "", + "PLAY RECAP *********************************************************************", + "testhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 " + ] \ No newline at end of file