Generate YAML output as well.

This commit is contained in:
Felix Fontein 2025-07-19 11:29:47 +02:00
commit 0741b65590
7 changed files with 636 additions and 49 deletions

View file

@ -10,3 +10,8 @@ ansible_output:
global_env: global_env:
ANSIBLE_STDOUT_CALLBACK: community.general.tasks_only ANSIBLE_STDOUT_CALLBACK: community.general.tasks_only
ANSIBLE_COLLECTIONS_TASKS_ONLY_NUMBER_OF_COLUMNS: 90 ANSIBLE_COLLECTIONS_TASKS_ONLY_NUMBER_OF_COLUMNS: 90
global_postprocessors:
reformat-yaml:
command:
- python
- docs/docsite/reformat-yaml.py

View file

@ -0,0 +1,27 @@
#!/usr/bin/env python
# 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
import sys
from io import StringIO
from ruamel.yaml import YAML
def main() -> None:
yaml = YAML(typ='rt')
yaml.indent(mapping=2, sequence=4, offset=2)
yaml.allow_duplicate_keys = True
# Load
data = yaml.load(sys.stdin)
# Dump
sio = StringIO()
yaml.dump(data, sio)
print(sio.getvalue().rstrip('\n'))
if __name__ == "__main__":
main()

View file

@ -37,24 +37,80 @@ Let us use the below list in the following examples:
gives gives
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 0
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
@{{ computation | indent(8) }}@
ansible.builtin.debug:
var: result
.. code-block:: yaml .. code-block:: yaml
:emphasize-lines: 1- :emphasize-lines: 1-
result: result:
- {k0_x0: A0, k1_x1: B0} - k0_x0: A0
- {k0_x0: A1, k1_x1: B1} k1_x1: B0
- k0_x0: A1
k1_x1: B1
.. versionadded:: 9.1.0 .. versionadded:: 9.1.0
* The results of the below examples 1-5 are all the same: * The results of the below examples 1-5 are all the same:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 0
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
# I picked one of the examples
mp: equal
target: ['k0_x0', 'k1_x1']
result: "{{ input | community.general.keep_keys(target=target, matching_parameter=mp) }}"
ansible.builtin.debug:
var: result
.. code-block:: yaml .. code-block:: yaml
:emphasize-lines: 1- :emphasize-lines: 1-
result: result:
- {k0_x0: A0, k1_x1: B0} - k0_x0: A0
- {k0_x0: A1, k1_x1: B1} k1_x1: B0
- k0_x0: A1
k1_x1: B1
1. Match keys that equal any of the items in the target. 1. Match keys that equal any of the items in the target.
@ -105,12 +161,40 @@ gives
* The results of the below examples 6-9 are all the same: * The results of the below examples 6-9 are all the same:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 0
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
# I picked one of the examples
mp: equal
target: k0_x0
result: "{{ input | community.general.keep_keys(target=target, matching_parameter=mp) }}"
ansible.builtin.debug:
var: result
.. code-block:: yaml .. code-block:: yaml
:emphasize-lines: 1- :emphasize-lines: 1-
result: result:
- {k0_x0: A0} - k0_x0: A0
- {k0_x0: A1} - k0_x0: A1
6. Match keys that equal the target. 6. Match keys that equal the target.
@ -148,4 +232,3 @@ gives
mp: regex mp: regex
target: ^.*0_x.*$ target: ^.*0_x.*$
result: "{{ input | community.general.keep_keys(target=target, matching_parameter=mp) }}" result: "{{ input | community.general.keep_keys(target=target, matching_parameter=mp) }}"

View file

@ -37,13 +37,39 @@ Let us use the below list in the following examples:
gives gives
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 0
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
@{{ computation | indent(8) }}@
ansible.builtin.debug:
var: result
.. code-block:: yaml .. code-block:: yaml
:emphasize-lines: 1- :emphasize-lines: 1-
result: result:
- k2_x2: [C0] - k2_x2:
- C0
k3_x3: foo k3_x3: foo
- k2_x2: [C1] - k2_x2:
- C1
k3_x3: bar k3_x3: bar
@ -51,13 +77,43 @@ gives
* The results of the below examples 1-5 are all the same: * The results of the below examples 1-5 are all the same:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 0
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
# I picked one of the examples
mp: equal
target: ['k0_x0', 'k1_x1']
result: "{{ input | community.general.remove_keys(target=target, matching_parameter=mp) }}"
ansible.builtin.debug:
var: result
.. code-block:: yaml .. code-block:: yaml
:emphasize-lines: 1- :emphasize-lines: 1-
result: result:
- k2_x2: [C0] - k2_x2:
- C0
k3_x3: foo k3_x3: foo
- k2_x2: [C1] - k2_x2:
- C1
k3_x3: bar k3_x3: bar
@ -109,15 +165,45 @@ gives
* The results of the below examples 6-9 are all the same: * The results of the below examples 6-9 are all the same:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 0
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
# I picked one of the examples
mp: equal
target: k0_x0
result: "{{ input | community.general.remove_keys(target=target, matching_parameter=mp) }}"
ansible.builtin.debug:
var: result
.. code-block:: yaml .. code-block:: yaml
:emphasize-lines: 1- :emphasize-lines: 1-
result: result:
- k1_x1: B0 - k1_x1: B0
k2_x2: [C0] k2_x2:
- C0
k3_x3: foo k3_x3: foo
- k1_x1: B1 - k1_x1: B1
k2_x2: [C1] k2_x2:
- C1
k3_x3: bar k3_x3: bar
@ -156,4 +242,3 @@ gives
mp: regex mp: regex
target: ^.*0_x.*$ target: ^.*0_x.*$
result: "{{ input | community.general.remove_keys(target=target, matching_parameter=mp) }}" result: "{{ input | community.general.remove_keys(target=target, matching_parameter=mp) }}"

View file

@ -40,17 +40,43 @@ Let us use the below list in the following examples:
gives gives
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 0
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
@{{ computation | indent(8) }}@
ansible.builtin.debug:
var: result
.. code-block:: yaml .. code-block:: yaml
:emphasize-lines: 1- :emphasize-lines: 1-
result: result:
- a0: A0 - a0: A0
a1: B0 a1: B0
k2_x2: [C0] k2_x2:
- C0
k3_x3: foo k3_x3: foo
- a0: A1 - a0: A1
a1: B1 a1: B1
k2_x2: [C1] k2_x2:
- C1
k3_x3: bar k3_x3: bar
@ -58,17 +84,49 @@ gives
* The results of the below examples 1-3 are all the same: * The results of the below examples 1-3 are all the same:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 0
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
# I picked one of the examples
mp: starts_with
target:
- {after: a0, before: k0}
- {after: a1, before: k1}
result: "{{ input | community.general.replace_keys(target=target, matching_parameter=mp) }}"
ansible.builtin.debug:
var: result
.. code-block:: yaml .. code-block:: yaml
:emphasize-lines: 1- :emphasize-lines: 1-
result: result:
- a0: A0 - a0: A0
a1: B0 a1: B0
k2_x2: [C0] k2_x2:
- C0
k3_x3: foo k3_x3: foo
- a0: A1 - a0: A1
a1: B1 a1: B1
k2_x2: [C1] k2_x2:
- C1
k3_x3: bar k3_x3: bar
@ -111,12 +169,41 @@ gives
* The results of the below examples 4-5 are the same: * The results of the below examples 4-5 are the same:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 0
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
# I picked one of the examples
mp: regex
target:
- {after: X, before: ^.*_x.*$}
result: "{{ input | community.general.replace_keys(target=target, matching_parameter=mp) }}"
ansible.builtin.debug:
var: result
.. code-block:: yaml .. code-block:: yaml
:emphasize-lines: 1- :emphasize-lines: 1-
result: result:
- {X: foo} - X: foo
- {X: bar} - X: bar
4. If more keys match the same attribute before the last one will be used. 4. If more keys match the same attribute before the last one will be used.
@ -165,11 +252,36 @@ gives
gives gives
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
@{{ computation | indent(8) }}@
ansible.builtin.debug:
var: result
.. code-block:: yaml .. code-block:: yaml
:emphasize-lines: 1- :emphasize-lines: 1-
result: result:
- {X: A, bbb1: B, ccc1: C} - X: A
- {X: D, bbb2: E, ccc2: F} bbb1: B
ccc1: C
- X: D
bbb2: E
ccc2: F

View file

@ -34,13 +34,42 @@ In the example below the lists are merged by the attribute ``name``:
This produces: This produces:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 0
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
@{{ computation | indent(8) }}@
ansible.builtin.debug:
var: list3
.. code-block:: yaml .. code-block:: yaml
list3: list3:
- {name: bar, extra: false} - extra: false
- {name: baz, path: /baz} name: bar
- {name: foo, extra: true, path: /foo} - name: baz
- {name: meh, extra: true} path: /baz
- extra: true
name: foo
path: /foo
- extra: true
name: meh
.. versionadded:: 2.0.0 .. versionadded:: 2.0.0
@ -56,13 +85,42 @@ It is possible to use a list of lists as an input of the filter:
This produces the same result as in the previous example: This produces the same result as in the previous example:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 0
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
@{{ computation | indent(8) }}@
ansible.builtin.debug:
var: list3
.. code-block:: yaml .. code-block:: yaml
list3: list3:
- {name: bar, extra: false} - extra: false
- {name: baz, path: /baz} name: bar
- {name: foo, extra: true, path: /foo} - name: baz
- {name: meh, extra: true} path: /baz
- extra: true
name: foo
path: /foo
- extra: true
name: meh
Single list Single list
""""""""""" """""""""""
@ -75,13 +133,42 @@ It is possible to merge single list:
This produces the same result as in the previous example: This produces the same result as in the previous example:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 0
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
@{{ computation | indent(8) }}@
ansible.builtin.debug:
var: list3
.. code-block:: yaml .. code-block:: yaml
list3: list3:
- {name: bar, extra: false} - extra: false
- {name: baz, path: /baz} name: bar
- {name: foo, extra: true, path: /foo} - name: baz
- {name: meh, extra: true} path: /baz
- extra: true
name: foo
path: /foo
- extra: true
name: meh
The filter also accepts two optional parameters: :ansopt:`community.general.lists_mergeby#filter:recursive` and :ansopt:`community.general.lists_mergeby#filter:list_merge`. This is available since community.general 4.4.0. The filter also accepts two optional parameters: :ansopt:`community.general.lists_mergeby#filter:recursive` and :ansopt:`community.general.lists_mergeby#filter:list_merge`. This is available since community.general 4.4.0.
@ -128,17 +215,45 @@ Example :ansopt:`community.general.lists_mergeby#filter:list_merge=replace` (def
This produces: This produces:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 4
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
@{{ computation | indent(8) }}@
ansible.builtin.debug:
var: list3
.. code-block:: yaml .. code-block:: yaml
list3: list3:
- name: myname01 - name: myname01
param01: param01:
list:
- patch_value
x: default_value x: default_value
y: patch_value y: patch_value
list: [patch_value]
z: patch_value z: patch_value
- name: myname02 - name: myname02
param01: [3, 4, 4] param01:
- 3
- 4
- 4
list_merge=keep list_merge=keep
""""""""""""""" """""""""""""""
@ -153,17 +268,46 @@ Example :ansopt:`community.general.lists_mergeby#filter:list_merge=keep`:
This produces: This produces:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 4
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
@{{ computation | indent(8) }}@
ansible.builtin.debug:
var: list3
.. code-block:: yaml .. code-block:: yaml
list3: list3:
- name: myname01 - name: myname01
param01: param01:
list:
- default_value
x: default_value x: default_value
y: patch_value y: patch_value
list: [default_value]
z: patch_value z: patch_value
- name: myname02 - name: myname02
param01: [1, 1, 2, 3] param01:
- 1
- 1
- 2
- 3
list_merge=append list_merge=append
""""""""""""""""" """""""""""""""""
@ -178,17 +322,50 @@ Example :ansopt:`community.general.lists_mergeby#filter:list_merge=append`:
This produces: This produces:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 4
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
@{{ computation | indent(8) }}@
ansible.builtin.debug:
var: list3
.. code-block:: yaml .. code-block:: yaml
list3: list3:
- name: myname01 - name: myname01
param01: param01:
list:
- default_value
- patch_value
x: default_value x: default_value
y: patch_value y: patch_value
list: [default_value, patch_value]
z: patch_value z: patch_value
- name: myname02 - name: myname02
param01: [1, 1, 2, 3, 3, 4, 4] param01:
- 1
- 1
- 2
- 3
- 3
- 4
- 4
list_merge=prepend list_merge=prepend
"""""""""""""""""" """"""""""""""""""
@ -203,17 +380,50 @@ Example :ansopt:`community.general.lists_mergeby#filter:list_merge=prepend`:
This produces: This produces:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 4
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
@{{ computation | indent(8) }}@
ansible.builtin.debug:
var: list3
.. code-block:: yaml .. code-block:: yaml
list3: list3:
- name: myname01 - name: myname01
param01: param01:
list:
- patch_value
- default_value
x: default_value x: default_value
y: patch_value y: patch_value
list: [patch_value, default_value]
z: patch_value z: patch_value
- name: myname02 - name: myname02
param01: [3, 4, 4, 1, 1, 2, 3] param01:
- 3
- 4
- 4
- 1
- 1
- 2
- 3
list_merge=append_rp list_merge=append_rp
"""""""""""""""""""" """"""""""""""""""""
@ -228,17 +438,49 @@ Example :ansopt:`community.general.lists_mergeby#filter:list_merge=append_rp`:
This produces: This produces:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 4
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
@{{ computation | indent(8) }}@
ansible.builtin.debug:
var: list3
.. code-block:: yaml .. code-block:: yaml
list3: list3:
- name: myname01 - name: myname01
param01: param01:
list:
- default_value
- patch_value
x: default_value x: default_value
y: patch_value y: patch_value
list: [default_value, patch_value]
z: patch_value z: patch_value
- name: myname02 - name: myname02
param01: [1, 1, 2, 3, 4, 4] param01:
- 1
- 1
- 2
- 3
- 4
- 4
list_merge=prepend_rp list_merge=prepend_rp
""""""""""""""""""""" """""""""""""""""""""
@ -253,15 +495,46 @@ Example :ansopt:`community.general.lists_mergeby#filter:list_merge=prepend_rp`:
This produces: This produces:
.. ansible-output-data::
env:
ANSIBLE_CALLBACK_RESULT_FORMAT: yaml
variables:
data:
previous_code_block: yaml
previous_code_block_index: 4
computation:
previous_code_block: yaml+jinja
postprocessors:
- name: reformat-yaml
language: yaml
skip_first_lines: 2
playbook: |-
- hosts: localhost
gather_facts: false
tasks:
- vars:
@{{ data | indent(8) }}@
@{{ computation | indent(8) }}@
ansible.builtin.debug:
var: list3
.. code-block:: yaml .. code-block:: yaml
list3: list3:
- name: myname01 - name: myname01
param01: param01:
list:
- patch_value
- default_value
x: default_value x: default_value
y: patch_value y: patch_value
list: [patch_value, default_value]
z: patch_value z: patch_value
- name: myname02 - name: myname02
param01: [3, 4, 4, 1, 1, 2] param01:
- 3
- 4
- 4
- 1
- 1
- 2

View file

@ -40,6 +40,8 @@ def ansible_output(session: nox.Session) -> None:
# Needed libs for some code blocks: # Needed libs for some code blocks:
"jc", "jc",
"hashids", "hashids",
# Tools for post-processing
"ruamel.yaml", # used by docs/docsite/reformat-yaml.py
) )
session.run("antsibull-docs", "ansible-output", *session.posargs) session.run("antsibull-docs", "ansible-output", *session.posargs)