团队
如何避免这种巨大的输出并从结果列表中的每个项目中获取我想要的值?
我只想显示主机名的项目值,并且仅显示每个主机的标准输出行。
- name: "Mount count on GPU Nodes"
shell: "mount | grep -Ec '/dev/sd.*\\<csi' | awk '{ print $0,\"mounts found on $HOSTNAME\"($0>64? \" that are more than 64.\" : \".\") }'"
register: mounts_count
changed_when: false
failed_when:
delegate_to: "{{ item }}"
with_items: "{{ groups['kube-gpu-node'] }}"
- name: Check if csi related mounts are present on gpu nodes
assert:
that:
- item.stdout is search('64')
fail_msg: " mounts are present on this node"
success_msg: "mounts are not present on this node"
loop: "{{ mounts_count.results }}"
loop_control:
label: "{{ item.item }}"
ignore_errors: yes
输出示例
TASK [team-services-pre-install-checks : Check if csi related mounts are present on gpu nodes] ***
Wednesday 18 December 2019 22:47:17 +0000 (0:00:07.012) 0:00:09.110 ****
failed: [localhost] (item=node1) => {
"ansible_loop_var": "item",
"assertion": "item.stdout is search('0')",
"changed": false,
"evaluated_to": false,
"item": {
"ansible_loop_var": "item",
"changed": false,
"cmd": "mount | grep -Ec '/dev/sd.*\\<csi' | awk '{ print $0,\"mounts found on hostname\"($0>64? \" that are more than 64.\" : \".\") }'",
"delta": "0:00:00.102618",
"end": "2019-12-18 22:47:12.566399",
"failed": false,
"invocation": {
"module_args": {
"_raw_params": "mount | grep -Ec '/dev/sd.*\\<csi' | awk '{ print $0,\"mounts found on hostname\"($0>64? \" that are more than 64.\" : \".\") }'",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true,
"warn": true
}
},
"item": "node1",
"rc": 0,
"start": "2019-12-18 22:47:12.463781",
"stderr": "",
"stderr_lines": [],
"stdout": "1 mounts found on hostname.",
"stdout_lines": [
"1 mounts found on hostname."
]
},
"msg": " mounts are present on this node"
}
ok: [localhost] => (item=node2) => {
"ansible_loop_var": "item",
"changed": false,
"item": {
"ansible_loop_var": "item",
"changed": false,
"cmd": "mount | grep -Ec '/dev/sd.*\\<csi' | awk '{ print $0,\"mounts found on hostname\"($0>64? \" that are more than 64.\" : \".\") }'",
"delta": "0:00:00.109244",
"end": "2019-12-18 22:47:14.303305",
"failed": false,
"invocation": {
"module_args": {
"_raw_params": "mount | grep -Ec '/dev/sd.*\\<csi' | awk '{ print $0,\"mounts found on hostname\"($0>64? \" that are more than 64.\" : \".\") }'",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true,
"warn": true
}
},
"item": "node2",
"rc": 0,
"start": "2019-12-18 22:47:14.194061",
"stderr": "",
"stderr_lines": [],
"stdout": "0 mounts found on hostname.",
"stdout_lines": [
"0 mounts found on hostname."
]
},
"msg": "mounts are not present on this node"
}
预期输出:下面只是我制作的手动示例,但任何显示主机名和 stdout_line 的东西都足够了。
"item": "node1"
0 mounts found on hostname.
"item": "node2"
0 mounts found on hostname.
Ansible 的设计初衷并不是为了在控制台上产生“漂亮”的输出。如果您希望以特定格式生成信息,最好从模板生成文件。
也就是说,
assert
模块主要被设计为调试工具并生成详细输出。我认为您可以使用 fail
模块获得您想要的行为:
- name: Check if csi related mounts are present on gpu nodes
fail:
msg: " mounts are present on this node"
when: item.stdout is not search('64')
loop: "{{ mounts_count.results }}"
loop_control:
label: "{{ item.item }}"
ignore_errors: yes
这将简单地“跳过”
when
条件为假的项目。
聚会有点晚了,但还是有解决办法的。
虽然 @larsks 关于良好输出的声明默认情况下是正确的,但我们有多种方法可以改进它。
ansible.builtin.keep_keys()
过滤器允许我们只选择足够的数据部分:
- name: Check if csi related mounts are present on gpu nodes
assert:
that:
- item.stdout is search('64')
fail_msg: " mounts are present on this node"
success_msg: "mounts are not present on this node"
loop: "{{ mounts_count.results | ansible.utils.keep_keys(['item', 'stdout']) }}"
loop_control:
label: "{{ item.item }}"
ignore_errors: yes
这会产生:
TASK [Check if csi related mounts are present on gpu nodes (by the OP)] ***********************************************************************************************************************
failed: [localhost] (item=localhost) => {
"ansible_loop_var": "item",
"assertion": "item.stdout is not search('6')",
"changed": false,
"evaluated_to": false,
"item": {
"item": "localhost",
"stdout": "7 mounts found on localhost that are more than 6."
},
"msg": " mounts are present on this node"
}
...ignoring
无需使用 shell 脚本,因为 Ansible 收集事实,其中包括节点的安装情况,因此您可以处理它们以进行报告(确保您有
gather_facts: true
正在播放):
- name: Check if csi related mounts are present on gpu nodes
debug:
msg: "{{ ansible_facts['ansible_mounts'] | length }} mounts found on {{ inventory_hostname }}"
failed_when: ansible_facts['ansible_mounts'] | length != 64
这会产生:
TASK [List the number of mounts] **************************************************************************************************************************************************************
ok: [test1] => {
"msg": "64 mounts found on test1"
}
fatal: [test2]: FAILED! => {
"msg": "0 mounts found on test2"
}
fatal: [test3]: FAILED! => {
"msg": "128 mounts found on test3"
请注意,这适用于 Linux 系统,不适用于 Mac OS。
此外,我们可以返回到
assert
模块,但它会比这更冗长一些:
- name: Check if csi related mounts are present on gpu nodes (using assert module, quiet = false)
vars:
message: "{{ ansible_facts['ansible_mounts'] | length }} mounts are present on this node"
assert:
that:
- ansible_facts['ansible_mounts'] | length != 64
fail_msg: "{{ message }}"
success_msg: "{{ message }}"
产生:
TASK [Check if csi related mounts are present on gpu nodes (using assert module, quiet = false)] **********************************************************************************************
fatal: [test1]: FAILED! => {
"assertion": "ansible_facts['ansible_mounts'] | length != 64",
"changed": false,
"evaluated_to": false,
"msg": "64 mounts are present on this node"
}
ok: [test2] => {
"changed": false,
"msg": "0 mounts are present on this node"
}
ok: [test3] => {
"changed": false,
"msg": "128 mounts are present on this node"
}
可以通过使用
quiet: true
来减少冗长:
- name: Check if csi related mounts are present on gpu nodes (using assert module, quiet = true)
vars:
message: "{{ number_of_mounts }} mounts are present on this node"
assert:
that:
- number_of_mounts | int != 64
fail_msg: "{{ message }}"
success_msg: "{{ message }}"
quiet: true
仅针对失败条件生成输出,这在报告中很有用:
TASK [Check if csi related mounts are present on gpu nodes (using assert module, quiet = true)] ***********************************************************************************************
fatal: [test1]: FAILED! => {"assertion": "number_of_mounts | int != 64", "changed": false, "evaluated_to": false, "msg": "64 mounts are present on this node"}
ok: [test2]
ok: [test3]
default
回调也相当灵活。例如,您可以利用 callback_result_format
和 callback_format_pretty
参数来帮助您摆脱 JSON 带来的过多符号和/或修复缩进,使日志变得更具可读性。您可以找到最适合您的组合。考虑以下示例ansible.cfg
:
[defaults]
callback_result_format = yaml
; callback_format_pretty is true by default when callback_result_format = yaml
无需对剧本进行任何修改,输出格式将得到改进:
TASK [Check if csi related mounts are present on gpu nodes (using debug module)] **************************************************************************************************************
ok: [test1] =>
msg: 64 mounts found on test1
fatal: [test2]: FAILED! =>
msg: 0 mounts found on test2
fatal: [test3]: FAILED! =>
msg: 128 mounts found on test3
TASK [Check if csi related mounts are present on gpu nodes (using assert module, quiet = false)] **********************************************************************************************
ok: [test1] =>
changed: false
msg: 64 mounts are present on this node
fatal: [test2]: FAILED! =>
assertion: ansible_facts['ansible_mounts'] | length == 64
changed: false
evaluated_to: false
msg: 0 mounts are present on this node
fatal: [test3]: FAILED! =>
assertion: ansible_facts['ansible_mounts'] | length == 64
changed: false
evaluated_to: false
msg: 128 mounts are present on this node
TASK [Check if csi related mounts are present on gpu nodes (using assert module, quiet = true)] ***********************************************************************************************
ok: [test1]
fatal: [test2]: FAILED! =>
assertion: ansible_facts['ansible_mounts'] | length == 64
changed: false
evaluated_to: false
msg: 0 mounts are present on this node
fatal: [test3]: FAILED! =>
assertion: ansible_facts['ansible_mounts'] | length == 64
changed: false
evaluated_to: false
msg: 128 mounts are present on this node
show_custom_stats
回调参数来在比赛回顾中使用自定义统计数据。它们可以通过set_stats
模块设置:
; ansible.cfg
callback_result_format = yaml
callback_format_pretty = true
show_custom_stats = true
# playbook.yaml
- name: Get the mount details using Ansible facts
hosts: kube_gpu_node
gather_facts: true
tasks:
- name: Set stats for mounts
set_stats:
data:
number_of_mounts: "{{ ansible_facts['ansible_mounts'] | length }}"
per_host: true
- name: Check if csi related mounts are present on gpu nodes (using debug module)
debug:
msg: "{{ ansible_facts['ansible_mounts'] | length }} mounts found on {{ inventory_hostname }}"
failed_when: ansible_facts['ansible_mounts'] | length != 64
请注意:
kube-gpu-node
不是有效的组名称,应使用下划线而不是连字符failed_when
不应与 set_stats
一起使用,因为即使使用 ignore_errors: true
,它也会在出现第一个错误时停止,并且不会为其他主机设置统计信息。因此,要进行正确的游戏回顾,您需要 debug
和 failed_when´ condition, or an
assert`。输出将是这样的:
PLAY [Get the mount details using Ansible facts] **********************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************************************
ok: [test3]
ok: [test2]
ok: [test1]
TASK [Set stats for mounts] *******************************************************************************************************************************************************************************
ok: [test1]
ok: [test2]
ok: [test3]
TASK [Check if csi related mounts are present on gpu nodes (using assert module, quiet = false)] **********************************************************************************************************
ok: [test1] =>
changed: false
msg: 64 mounts are present on this node
fatal: [test2]: FAILED! =>
assertion: number_of_mounts | int == 64
changed: false
evaluated_to: false
msg: 0 mounts are present on this node
fatal: [test3]: FAILED! =>
assertion: number_of_mounts | int == 64
changed: false
evaluated_to: false
msg: 128 mounts are present on this node
PLAY RECAP ************************************************************************************************************************************************************************************************
test1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
test2 : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
test3 : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
CUSTOM STATS: *********************************************************************************************************************************************************************************************
test1: number_of_mounts: 64
test2: number_of_mounts: 0
test3: number_of_mounts: 128