From 2cedaa24b6b0d7cbe691f8aae0f23764ccdb38dd Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 7 Jan 2026 13:55:26 +0100 Subject: [PATCH] default callback: make YAML line width configurable (#85498) * Make YAML line width configurable. Co-authored-by: Abhijeet Kasurde --- .../85498-default-callback-width.yml | 3 +++ lib/ansible/plugins/callback/__init__.py | 21 ++++++++++++++++ .../doc_fragments/result_format_callback.py | 16 ++++++++++++ ...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, 106 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 43188cb0357..0f2a3f7d84b 100644 --- a/lib/ansible/plugins/callback/__init__.py +++ b/lib/ansible/plugins/callback/__init__.py @@ -262,6 +262,25 @@ 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 + + match yaml_line_width: + case 'default': + return None + case 'no-break': + # Some very large value that effectively disables line breaks + return 0x7FFFFFFF + case 'terminal-width': + return self._display.columns + case _: + 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 +365,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 +435,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..c22ebeac253 100644 --- a/lib/ansible/plugins/doc_fragments/result_format_callback.py +++ b/lib/ansible/plugins/doc_fragments/result_format_callback.py @@ -41,6 +41,22 @@ 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. + type: str + default: default + choices: + default: Use PyYAML's default value, which is around 80 characters. + no-break: Disable line breaks. + terminal-width: Use the detected terminal width that is also used for other output of this callback. + env: + - name: ANSIBLE_CALLBACK_YAML_LINE_WIDTH + ini: + - key: callback_result_yaml_line_width + section: defaults + version_added: '2.21' 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.