From 60cc471d9ebd7cc8ddb7fe07d21becc4c7f6466d Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 16 Jul 2025 21:08:13 +0200 Subject: [PATCH 1/2] Make YAML line width configurable. --- .../85498-default-callback-width.yml | 3 +++ lib/ansible/plugins/callback/__init__.py | 20 +++++++++++++++ .../doc_fragments/result_format_callback.py | 19 ++++++++++++++ ...ut.result_format_yaml_default_break.stderr | 2 ++ ...ut.result_format_yaml_default_break.stdout | 25 +++++++++++++++++++ ...ult.out.result_format_yaml_no_break.stderr | 2 ++ ...ult.out.result_format_yaml_no_break.stdout | 16 ++++++++++++ .../targets/callback_default/runme.sh | 8 ++++++ .../callback_default/test_long_line.yml | 13 ++++++++++ 9 files changed, 108 insertions(+) create mode 100644 changelogs/fragments/85498-default-callback-width.yml create mode 100644 test/integration/targets/callback_default/callback_default.out.result_format_yaml_default_break.stderr create mode 100644 test/integration/targets/callback_default/callback_default.out.result_format_yaml_default_break.stdout create mode 100644 test/integration/targets/callback_default/callback_default.out.result_format_yaml_no_break.stderr create mode 100644 test/integration/targets/callback_default/callback_default.out.result_format_yaml_no_break.stdout create mode 100644 test/integration/targets/callback_default/test_long_line.yml diff --git a/changelogs/fragments/85498-default-callback-width.yml b/changelogs/fragments/85498-default-callback-width.yml new file mode 100644 index 00000000000..b6dbef8156d --- /dev/null +++ b/changelogs/fragments/85498-default-callback-width.yml @@ -0,0 +1,3 @@ +minor_changes: + - "default callback plugin - add option to configure line width for YAML output. This allows to disable line wrapping + (https://github.com/ansible/ansible/issues/84657, https://github.com/ansible/ansible/pull/85498)." diff --git a/lib/ansible/plugins/callback/__init__.py b/lib/ansible/plugins/callback/__init__.py index 944606f26ff..0d6cf473f6a 100644 --- a/lib/ansible/plugins/callback/__init__.py +++ b/lib/ansible/plugins/callback/__init__.py @@ -262,6 +262,24 @@ class CallbackBase(AnsiblePlugin): return ((self._display.verbosity > verbosity or result.result.get('_ansible_verbose_always', False) is True) and result.result.get('_ansible_verbose_override', False) is False) + def _get_yaml_width(self) -> t.Optional[int]: + try: + yaml_line_width = self.get_option('result_yaml_line_width') + except KeyError: + # Callback does not declare result_yaml_line_width nor extend result_format_callback + return None + + if yaml_line_width == 'default': + return None + if yaml_line_width == 'no-break': + # Some very large value that effectively disables line breaks + return 0x7FFFFFFF + if yaml_line_width == 'terminal-width': + return self._display.columns + + self._display.warn(f"Invalid value {yaml_line_width!r} for result_yaml_line_width") + return None + def _dump_results( self, result: _c.Mapping[str, t.Any], @@ -346,6 +364,7 @@ class CallbackBase(AnsiblePlugin): Dumper=functools.partial(_AnsibleCallbackDumper, lossy=lossy), default_flow_style=False, indent=indent, + width=self._get_yaml_width(), # sort_keys=sort_keys # This requires PyYAML>=5.1 ), ' ' * (indent or 4) @@ -415,6 +434,7 @@ class CallbackBase(AnsiblePlugin): Dumper=functools.partial(_AnsibleCallbackDumper, lossy=lossy), default_flow_style=False, indent=indent, + width=self._get_yaml_width(), # sort_keys=sort_keys # This requires PyYAML>=5.1 ), ' ' diff --git a/lib/ansible/plugins/doc_fragments/result_format_callback.py b/lib/ansible/plugins/doc_fragments/result_format_callback.py index 220a311bab0..0f2325db5b2 100644 --- a/lib/ansible/plugins/doc_fragments/result_format_callback.py +++ b/lib/ansible/plugins/doc_fragments/result_format_callback.py @@ -41,6 +41,25 @@ class ModuleDocFragment(object): - key: callback_result_indentation section: defaults version_added: '2.20' + result_yaml_line_width: + name: Line width of YAML output + description: + - Configure the line width used for YAML. The YAML serializer will try to break longer lines. + - Set to V(default) for the PyYAML's default value, which is around 80 characters. + - Set to V(no-break) to disable line breaks. + - Set to V(terminal-width) to use the detected terminal width that is also used for other output of this callback. + type: str + default: default + choices: + - default + - no-break + - terminal-width + env: + - name: ANSIBLE_CALLBACK_YAML_LINE_WIDTH + ini: + - key: callback_result_yaml_line_width + section: defaults + version_added: '2.20' pretty_results: name: Configure output for readability description: diff --git a/test/integration/targets/callback_default/callback_default.out.result_format_yaml_default_break.stderr b/test/integration/targets/callback_default/callback_default.out.result_format_yaml_default_break.stderr new file mode 100644 index 00000000000..f4c6106ff6a --- /dev/null +++ b/test/integration/targets/callback_default/callback_default.out.result_format_yaml_default_break.stderr @@ -0,0 +1,2 @@ ++ ansible-playbook -i inventory test_long_line.yml +++ set +x diff --git a/test/integration/targets/callback_default/callback_default.out.result_format_yaml_default_break.stdout b/test/integration/targets/callback_default/callback_default.out.result_format_yaml_default_break.stdout new file mode 100644 index 00000000000..b0c335d33ee --- /dev/null +++ b/test/integration/targets/callback_default/callback_default.out.result_format_yaml_default_break.stdout @@ -0,0 +1,25 @@ + +PLAY [localhost] *************************************************************** + +TASK [Output with long line] *************************************************** +ok: [localhost] => + msg: + - This is a normal line. + - This is a very, very, verrrrrrrrrrrrrrry, veryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong + line. + - a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n + o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a + b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n + o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z + - Another normal line: + - Some nested line. + - A nested very, very, verrrrrrrrrrrrrrry, veryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong + line. + +PLAY RECAP ********************************************************************* +localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 + diff --git a/test/integration/targets/callback_default/callback_default.out.result_format_yaml_no_break.stderr b/test/integration/targets/callback_default/callback_default.out.result_format_yaml_no_break.stderr new file mode 100644 index 00000000000..f4c6106ff6a --- /dev/null +++ b/test/integration/targets/callback_default/callback_default.out.result_format_yaml_no_break.stderr @@ -0,0 +1,2 @@ ++ ansible-playbook -i inventory test_long_line.yml +++ set +x diff --git a/test/integration/targets/callback_default/callback_default.out.result_format_yaml_no_break.stdout b/test/integration/targets/callback_default/callback_default.out.result_format_yaml_no_break.stdout new file mode 100644 index 00000000000..ee130afabc2 --- /dev/null +++ b/test/integration/targets/callback_default/callback_default.out.result_format_yaml_no_break.stdout @@ -0,0 +1,16 @@ + +PLAY [localhost] *************************************************************** + +TASK [Output with long line] *************************************************** +ok: [localhost] => + msg: + - This is a normal line. + - This is a very, very, verrrrrrrrrrrrrrry, veryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line. + - a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z + - Another normal line: + - Some nested line. + - A nested very, very, verrrrrrrrrrrrrrry, veryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line. + +PLAY RECAP ********************************************************************* +localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 + diff --git a/test/integration/targets/callback_default/runme.sh b/test/integration/targets/callback_default/runme.sh index 9936b9ad664..b73d3f24dfd 100755 --- a/test/integration/targets/callback_default/runme.sh +++ b/test/integration/targets/callback_default/runme.sh @@ -208,6 +208,14 @@ run_test result_format_yaml_indent_2 test.yml export ANSIBLE_CALLBACK_RESULT_FORMAT=json unset ANSIBLE_CALLBACK_RESULT_INDENTATION +export ANSIBLE_CALLBACK_RESULT_FORMAT=yaml +export ANSIBLE_CALLBACK_YAML_LINE_WIDTH=default +run_test result_format_yaml_default_break test_long_line.yml +export ANSIBLE_CALLBACK_YAML_LINE_WIDTH=no-break +run_test result_format_yaml_no_break test_long_line.yml +export ANSIBLE_CALLBACK_RESULT_FORMAT=json +unset ANSIBLE_CALLBACK_YAML_LINE_WIDTH + export ANSIBLE_CALLBACK_RESULT_FORMAT=yaml export ANSIBLE_CALLBACK_FORMAT_PRETTY=1 run_test result_format_yaml_lossy_verbose test.yml -v diff --git a/test/integration/targets/callback_default/test_long_line.yml b/test/integration/targets/callback_default/test_long_line.yml new file mode 100644 index 00000000000..219abef5b57 --- /dev/null +++ b/test/integration/targets/callback_default/test_long_line.yml @@ -0,0 +1,13 @@ +--- +- hosts: localhost + gather_facts: false + tasks: + - name: Output with long line + debug: + msg: + - This is a normal line. + - This is a very, very, verrrrrrrrrrrrrrry, veryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line. + - a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z + - Another normal line: + - Some nested line. + - A nested very, very, verrrrrrrrrrrrrrry, veryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line. From 0d5309f7225072c506a6d2fbf76f8096941dabb3 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 29 Oct 2025 19:31:57 +0100 Subject: [PATCH 2/2] Update version_added. Co-authored-by: Abhijeet Kasurde --- lib/ansible/plugins/doc_fragments/result_format_callback.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ansible/plugins/doc_fragments/result_format_callback.py b/lib/ansible/plugins/doc_fragments/result_format_callback.py index 0f2325db5b2..140417c83a8 100644 --- a/lib/ansible/plugins/doc_fragments/result_format_callback.py +++ b/lib/ansible/plugins/doc_fragments/result_format_callback.py @@ -59,7 +59,7 @@ class ModuleDocFragment(object): ini: - key: callback_result_yaml_line_width section: defaults - version_added: '2.20' + version_added: '2.21' pretty_results: name: Configure output for readability description: