diff --git a/changelogs/fragments/fix_ansible-doc_colors_without_tty.yaml b/changelogs/fragments/fix_ansible-doc_colors_without_tty.yaml new file mode 100644 index 00000000000..7fa96885e51 --- /dev/null +++ b/changelogs/fragments/fix_ansible-doc_colors_without_tty.yaml @@ -0,0 +1,2 @@ +bugfixes: + - ansible-doc - don't write ansi escape sequences without interactive tty / respect ANSIBLE_COLOR diff --git a/lib/ansible/cli/doc.py b/lib/ansible/cli/doc.py index d591e000a9e..6aa09edac9d 100755 --- a/lib/ansible/cli/doc.py +++ b/lib/ansible/cli/doc.py @@ -40,7 +40,7 @@ from ansible.plugins.list import _list_plugins_with_info, _PluginDocMetadata from ansible.plugins.loader import action_loader, fragment_loader from ansible.utils.collection_loader import AnsibleCollectionConfig, AnsibleCollectionRef from ansible.utils.collection_loader._collection_finder import _get_collection_name_from_path -from ansible.utils.color import stringc +from ansible.utils.color import ANSIBLE_COLOR, stringc from ansible.utils.display import Display from ansible.utils.plugin_docs import get_plugin_docs, get_docstring, get_versioned_doclink from ansible.template import trust_as_template @@ -423,7 +423,7 @@ def _format(string, *args): if style not in ref_style and style.upper() not in STYLE and style not in C.COLOR_CODES: raise KeyError("Invalid format value supplied: %s" % style) - if C.ANSIBLE_NOCOLOR: + if C.ANSIBLE_NOCOLOR or not ANSIBLE_COLOR: # ignore most styles, but some already had 'identifier strings' if style in NOCOLOR: string = NOCOLOR[style] % string diff --git a/test/integration/targets/ansible-doc/test.yml b/test/integration/targets/ansible-doc/test.yml index fbf36ae2593..625473b1fb5 100644 --- a/test/integration/targets/ansible-doc/test.yml +++ b/test/integration/targets/ansible-doc/test.yml @@ -1,15 +1,44 @@ - hosts: localhost - gather_facts: no + gather_facts: false environment: - ANSIBLE_LIBRARY: "{{ playbook_dir }}/library" - ANSIBLE_NOCOLOR: 1 ANSIBLE_DEPRECATION_WARNINGS: 1 ANSIBLE_DOC_FRAGMENT_PLUGINS: "{{ playbook_dir }}/doc_fragments" + ANSIBLE_LIBRARY: "{{ playbook_dir }}/library" + ANSIBLE_NOCOLOR: 1 vars: # avoid header that has full path and won't work across random paths for tests actual_output_clean: '{{ actual_output.splitlines()[1:] }}' expected_output_clean: '{{ expected_output.splitlines()[1:] }}' tasks: + - name: create temporary file + ansible.builtin.tempfile: + state: file + register: temp_file + + - name: redirect stdout and stderr to file + ansible.builtin.shell: | + ansible-doc test_docs > {{ temp_file.path }} 2>&1 + environment: + ANSIBLE_DEPRECATION_WARNINGS: 0 + ANSIBLE_DEVEL_WARNING: 0 + ANSIBLE_FORCE_COLOR: 0 + ANSIBLE_NOCOLOR: 0 + + - name: assert that file does not contain ansi escape sequences + assert: + that: + - actual_output[0][:20] == "> MODULE test_docs (" + fail_msg: | + actual_output[0][:20]: {{ actual_output[0][:20] }} + actual_output: {{ actual_output }} + vars: + actual_output: "{{ lookup('file', temp_file.path).splitlines() }}" + + - name: remove tempfile + ansible.builtin.file: + path: "{{ temp_file.path }}" + state: absent + - name: module with missing description return docs command: ansible-doc test_docs_missing_description register: result