From 3207e55ca24ac0959984155f8a52c842b97bba04 Mon Sep 17 00:00:00 2001 From: Matt Clay Date: Wed, 21 May 2025 10:42:22 -0700 Subject: [PATCH] display - Replace CRNL with NL (#85194) (cherry picked from commit e2262948558d7181a874aecac2b4394d3a7cd174) --- changelogs/fragments/display-windows-newline.yml | 4 ++++ lib/ansible/utils/display.py | 4 ++++ test/integration/targets/display-newline/aliases | 3 +++ .../targets/display-newline/library/noisy.py | 13 +++++++++++++ .../targets/display-newline/tasks/main.yml | 10 ++++++++++ 5 files changed, 34 insertions(+) create mode 100644 changelogs/fragments/display-windows-newline.yml create mode 100644 test/integration/targets/display-newline/aliases create mode 100644 test/integration/targets/display-newline/library/noisy.py create mode 100644 test/integration/targets/display-newline/tasks/main.yml diff --git a/changelogs/fragments/display-windows-newline.yml b/changelogs/fragments/display-windows-newline.yml new file mode 100644 index 00000000000..c4d4887d4c5 --- /dev/null +++ b/changelogs/fragments/display-windows-newline.yml @@ -0,0 +1,4 @@ +minor_changes: + - display - Replace Windows newlines (``\r\n``) in display output with Unix newlines (``\n``). + This ensures proper display of strings sourced from Windows hosts in environments which treat ``\r`` as ``\n``, + such as Azure Pipelines. diff --git a/lib/ansible/utils/display.py b/lib/ansible/utils/display.py index e0a2bf73e60..cd369da7205 100644 --- a/lib/ansible/utils/display.py +++ b/lib/ansible/utils/display.py @@ -437,6 +437,10 @@ class Display(metaclass=Singleton): if not isinstance(msg, str): raise TypeError(f'Display message must be str, not: {msg.__class__.__name__}') + # Convert Windows newlines to Unix newlines. + # Some environments, such as Azure Pipelines, render `\r` as an additional `\n`. + msg = msg.replace('\r\n', '\n') + nocolor = msg if not log_only: diff --git a/test/integration/targets/display-newline/aliases b/test/integration/targets/display-newline/aliases new file mode 100644 index 00000000000..ea8d1627352 --- /dev/null +++ b/test/integration/targets/display-newline/aliases @@ -0,0 +1,3 @@ +shippable/posix/group5 +context/controller +gather_facts/no diff --git a/test/integration/targets/display-newline/library/noisy.py b/test/integration/targets/display-newline/library/noisy.py new file mode 100644 index 00000000000..ba7c7461d6f --- /dev/null +++ b/test/integration/targets/display-newline/library/noisy.py @@ -0,0 +1,13 @@ +from __future__ import annotations + +from ansible.module_utils.basic import AnsibleModule + + +def main() -> None: + m = AnsibleModule({}) + m.warn("Hello\r\nNew\rAnsible\nWorld") + m.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/display-newline/tasks/main.yml b/test/integration/targets/display-newline/tasks/main.yml new file mode 100644 index 00000000000..df8243b091a --- /dev/null +++ b/test/integration/targets/display-newline/tasks/main.yml @@ -0,0 +1,10 @@ +- name: Run a command which generates a warning with NL, CR and CRNL + command: ansible -m noisy localhost + register: result + environment: + ANSIBLE_FORCE_COLOR: 0 + ANSIBLE_LIBRARY: "{{ role_path }}/library" + +- name: Verify NL and CR are preserved, but CRNL is converted to NL + assert: + that: result.stderr is contains 'Hello\nNew\rAnsible\nWorld'