Ansible:如何将受任务影响的所有主机存储在变量中?
Ansible: how to store all hosts affected by a task in a variable?
我有一个针对一小组主机的剧本,还有一个任务可以根据我设置变量的方式更改其中一个或多个主机上的一些配置文件。
运行 此任务的简化示例结果:
TASK [somerole : create config file] *************************************
ok: [server1] => (item=foo.conf)
changed: [server2] => (item=foo.conf)
changed: [server3] => (item=foo.conf)
如果我在此任务上使用 register
,然后 debug
它创建的变量,debug: var=varname
的输出将如下所示(大大简化):
TASK [somerole : debug] **************************************************
ok: [server1] => {
"varname": {
"changed": false,
"results": [{...}]
}
}
ok: [server2] => {
"varname": {
"changed": true,
"results": [{...}]
}
}
ok: [server3] => {
"varname": {
"changed": true,
"results": [{...}]
}
}
配置更改需要重新启动服务,目前必须由人工手动完成(有手动目测验证步骤)。为了解决这个问题,我想在剧本末尾使用 pause
模块向用户显示提示,如下所示:
- pause:
prompt: |-
The configuration has changed on the following servers: {{ changed_servers|join(', ' }}
Please restart service X on these servers after validating Y and Z.
那么,如何构建 changed_servers
变量?鉴于上面的例子,它将是这个列表:["server2", "server3"]
(因为它们是这次任务更改的主机)。
我首先想到我会尝试组合 register
为每个受任务影响的主机生成的 varname
变量,查看每个主机中的 changed
布尔值,但是varname
中的任何地方都不存在主机名称,因此我可以将 changed
属性与相应主机的名称结合起来。
真的有办法做到这一点吗?
问:"将受任务影响的所有主机存储在变量中"
A:用任务的结果注册一个变量。然后使用 extract 收集结果。例如,下面的剧本创建文件 foo.conf 注册结果并创建字典 dict_foo_conf
- hosts: test_11,test_12,test_13
tasks:
- command:
cmd: touch foo.conf
creates: foo.conf
warn: false
register: result_foo_conf
- set_fact:
dict_foo_conf: "{{ dict(ansible_play_hosts_all|zip(my_results)) }}"
vars:
my_results: "{{ ansible_play_hosts_all|
map('extract', hostvars, ['result_foo_conf', 'changed'])|
list }}"
run_once: true
给予
TASK [command] *************************************************************
changed: [test_11]
changed: [test_12]
changed: [test_13]
dict_foo_conf:
test_11: true
test_12: true
test_13: true
当您再次运行剧本时没有任何变化
TASK [command] ******************************************************************
ok: [test_13]
ok: [test_11]
ok: [test_12]
dict_foo_conf:
test_11: false
test_12: false
test_13: false
让我们从主机 test_12 和 test_13
中删除文件
shell> ssh admin@test_12 rm foo.conf
shell> ssh admin@test_13 rm foo.conf
剧本给出
TASK [command] ******************************************************************
changed: [test_12]
ok: [test_11]
changed: [test_13]
dict_foo_conf:
test_11: false
test_12: true
test_13: true
然后 select 发生变化的主机,例如
- set_fact:
changed_hosts: "{{ dict_foo_conf|dict2items|json_query('[?value].key') }}"
给予
changed_hosts:
- test_12
- test_13
我有一个针对一小组主机的剧本,还有一个任务可以根据我设置变量的方式更改其中一个或多个主机上的一些配置文件。
运行 此任务的简化示例结果:
TASK [somerole : create config file] *************************************
ok: [server1] => (item=foo.conf)
changed: [server2] => (item=foo.conf)
changed: [server3] => (item=foo.conf)
如果我在此任务上使用 register
,然后 debug
它创建的变量,debug: var=varname
的输出将如下所示(大大简化):
TASK [somerole : debug] **************************************************
ok: [server1] => {
"varname": {
"changed": false,
"results": [{...}]
}
}
ok: [server2] => {
"varname": {
"changed": true,
"results": [{...}]
}
}
ok: [server3] => {
"varname": {
"changed": true,
"results": [{...}]
}
}
配置更改需要重新启动服务,目前必须由人工手动完成(有手动目测验证步骤)。为了解决这个问题,我想在剧本末尾使用 pause
模块向用户显示提示,如下所示:
- pause:
prompt: |-
The configuration has changed on the following servers: {{ changed_servers|join(', ' }}
Please restart service X on these servers after validating Y and Z.
那么,如何构建 changed_servers
变量?鉴于上面的例子,它将是这个列表:["server2", "server3"]
(因为它们是这次任务更改的主机)。
我首先想到我会尝试组合 register
为每个受任务影响的主机生成的 varname
变量,查看每个主机中的 changed
布尔值,但是varname
中的任何地方都不存在主机名称,因此我可以将 changed
属性与相应主机的名称结合起来。
真的有办法做到这一点吗?
问:"将受任务影响的所有主机存储在变量中"
A:用任务的结果注册一个变量。然后使用 extract 收集结果。例如,下面的剧本创建文件 foo.conf 注册结果并创建字典 dict_foo_conf
- hosts: test_11,test_12,test_13
tasks:
- command:
cmd: touch foo.conf
creates: foo.conf
warn: false
register: result_foo_conf
- set_fact:
dict_foo_conf: "{{ dict(ansible_play_hosts_all|zip(my_results)) }}"
vars:
my_results: "{{ ansible_play_hosts_all|
map('extract', hostvars, ['result_foo_conf', 'changed'])|
list }}"
run_once: true
给予
TASK [command] *************************************************************
changed: [test_11]
changed: [test_12]
changed: [test_13]
dict_foo_conf:
test_11: true
test_12: true
test_13: true
当您再次运行剧本时没有任何变化
TASK [command] ******************************************************************
ok: [test_13]
ok: [test_11]
ok: [test_12]
dict_foo_conf:
test_11: false
test_12: false
test_13: false
让我们从主机 test_12 和 test_13
中删除文件shell> ssh admin@test_12 rm foo.conf
shell> ssh admin@test_13 rm foo.conf
剧本给出
TASK [command] ******************************************************************
changed: [test_12]
ok: [test_11]
changed: [test_13]
dict_foo_conf:
test_11: false
test_12: true
test_13: true
然后 select 发生变化的主机,例如
- set_fact:
changed_hosts: "{{ dict_foo_conf|dict2items|json_query('[?value].key') }}"
给予
changed_hosts:
- test_12
- test_13