查找清单中每个主机的主机变量列表

问题描述 投票:0回答:4

我正在尝试找到一种使用 Ansible 调试模块创建以下结果的方法。

期望的结果

{
  "myserver01": {
    "host_var_one": "foo",
    "host_var_two": "bar"
  },
  "myserver02": {
    "host_var_one": "biz",
    "host_var_two": "baz"
  },
  "myserver03": {
    "host_var_one": "fizz",
    "host_var_two": "buzz"
  }
}

库存示例

[my_servers]
myserver01 host_var_one=foo host_var_two=bar
myserver02 host_var_one=biz host_var_two=baz
myserver03 host_var_one=fizz host_var_two=buzz

我希望能够提供一个主机变量列表,并将它们显示在清单中每个主机下的字典中,其中键是主机变量名称,值是主机变量值。理想情况下,在结果中包含另一个主机变量应该只需要向列表中添加另一个变量名称即可。

例如,在任务中,我会为清单中的每个主机列出我想要的

["host_var_one", "host_var_two"]
,并获得上述所需的结果。

我有以下任务,它“在某种程度上”接近我想要的。我只是想不出一种方法以上述格式列出每个主机所需的所有变量。以下仅适用于一个变量,并且没有列出变量名称和值。

myplaybook.yml

--- - name: Test hosts: all gather_facts: yes user: ansible become: yes tasks: - name: Debug debug: msg: "{{ dict(query('inventory_hostnames', 'all') | zip(query('inventory_hostnames', 'all') | map('extract', hostvars, 'host_var_one'))) }}" run_once: yes

myplaybook.yml 的结果

$ ansible-playbook -i inventory test.yml --limit "myserver01" PLAY [Test] ************************************************************************************************************************************************** TASK [Gathering Facts] *************************************************************************************************************************************** ok: [myserver01] TASK [Debug] ************************************************************************************************************************************************* ok: [myserver01] => { "msg": { "myserver01": "foo", "myserver02": "biz", "myserver03": "fizz" } }

	
ansible jinja2
4个回答
5
投票

- name: Dict of host_vars debug: msg: "{{ dict( keys | zip(values) ) }}" vars: keys: "{{ hostvars | dict2items | map(attribute='key') }}" values: "{{ hostvars | dict2items | map(attribute='value') | map('dict2items') | map('selectattr', 'key', 'match', 'host_var_') | map('items2dict') }}" run_once: yes

结果如下:

TASK [Host vars dict] ************************************************** ok: [myserver01] => { "msg": { "myserver01": { "host_var_one": "foo", "host_var_two": "bar" }, "myserver02": { "host_var_one": "biz", "host_var_two": "baz" }, "myserver03": { "host_var_one": "fizz", "host_var_two": "buzz" } } }

逐步说明

创建了两个单独的列表:

keys

values

keys

的列表是通过用

dict2items
转换字典来创建的,这样
key
就可以提取属性
map
。这样你就可以得到列表了:
[ "myserver01", "myserver02", "myserver03" ]

对于 
values

,其工作方式相同,即生成

value
属性列表。这些列表在每种情况下都是字典,因此必须通过
map('dict2items')
再次转换为列表。现在可以通过
key
在列表中过滤
selectattr
。这里
host_var_
match
(字符串的开头)过滤掉。然后,结果(列表中的列表)必须通过
map('items2dict')
转换回字典。
[
  {
    "host_var_one": "foo",
    "host_var_two": "bar"
  },
  {
    "host_var_one": "biz",
    "host_var_two": "baz"
  },
  {
    "host_var_one": "fizz",
    "host_var_two": "buzz"
  }
]

最后,通过 
zip

合并两个列表,并通过

dict
转换回一个列表。
按前缀过滤的变量

变量是通过其名称的前缀来过滤的,因此可以为不同的主机定义多个不同的变量(具有相同的前缀),并且将被完全过滤掉。

例如库存:

[my_servers] myserver01 host_var_one=foo host_var_two=bar myserver02 host_var_one=biz host_var_two=baz host_var_three=boz host_var_four=buz myserver03 host_var_one=fizz host_var_two=buzz host_var_six=dazz

返回以下结果:

TASK [Dict of host_vars] ********************************************** ok: [myserver01] => { "msg": { "myserver01": { "host_var_one": "foo", "host_var_two": "bar" }, "myserver02": { "host_var_four": "buz", "host_var_one": "biz", "host_var_three": "boz", "host_var_two": "baz" }, "myserver03": { "host_var_one": "fizz", "host_var_six": "dazz", "host_var_two": "buzz" } } }



3
投票
vars

selection: "{{ dict(ansible_play_hosts_all| zip(hostvars|json_query(_query))) }}" _query: '*.{host_var_one: host_var_one, host_var_two: host_var_two}'

鉴于上述库存,结果是

selection: myserver01: host_var_one: foo host_var_two: bar myserver02: host_var_one: biz host_var_two: baz myserver03: host_var_one: fizz host_var_two: buzz

在字典中,所有主机都保留由公共
_query

选择的相同变量。


用于测试的完整剧本示例

- hosts: my_servers gather_facts: false vars: selection: "{{ dict(ansible_play_hosts_all| zip(hostvars|json_query(_query))) }}" _query: '*.{host_var_one: host_var_one, host_var_two: host_var_two}' tasks: - debug: var: selection run_once: true


问:

“列出清单中每个主机的变量。” A:例如,给定库存

shell> cat hosts all: children: my_servers: hosts: myserver01: host_var_one: foo host_var_two: bar host_var_three: baz sel_vars: [host_var_one, host_var_two, host_var_three] myserver02: host_var_one: biz host_var_two: baz sel_vars: [host_var_one, host_var_two] myserver03: host_var_one: fiz host_var_two: buz sel_vars: [host_var_two]

下面的剧本

- hosts: my_servers gather_facts: false vars: sel_vals: "{{ sel_vars|map('extract', vars)|list }}" sel_dict: "{{ dict(sel_vars|zip(sel_vals)) }}" sel_all: "{{ ansible_play_hosts_all|map('extract', hostvars, 'sel_dict') }}" selection: "{{ dict(ansible_play_hosts_all|zip(sel_all)) }}" tasks: - set_fact: sel_dict: "{{ sel_dict }}" - debug: var: selection run_once: true

给出(删节)

selection: myserver01: host_var_one: foo host_var_three: baz host_var_two: bar myserver02: host_var_one: biz host_var_two: baz myserver03: host_var_two: buz

任务 
set_fact

对于所有主机“实例化”(在 hostvars 中创建)变量 sel_dict 是必需的。 您可以动态选择变量。例如,将以下声明放入

vars

sel_vars: "{{ query('varnames', '.*_one') }}"

结果将会是

selection: myserver01: host_var_one: foo myserver02: host_var_one: biz myserver03: host_var_one: fiz



2
投票

json_query

在处理顶级字典方面很烂,所以一点点
dict2items
将其旋转为一个字典数组, JMESPath 更擅长处理,将项目投影到与您想要的东西相同的 
[{key: .key, value: ...}]
形状中,然后将其旋转回具有相反过滤器的字典 (
items2dict
)
  - debug:
      msg: '{{ hostvars | dict2items | json_query(jq) | items2dict }}'
    delegate_to: localhost
    run_once: true
    vars:
      jq: '[*].{key: key, value: {one: value.host_var_one, two: value.host_var_two}}'

产生

ok: [alpha -> localhost] => { "msg": { "alpha": { "one": "a1", "two": "a2" }, "beta": { "one": "b1", "two": "b2" } } }

我没有遵循你对

zip所做的事情,但据我所知,

hostvars
包含
所有
主机变量,因此不需要zip欺骗

或者,如果你有一个巨大的列表,或者一个未知的列表,要提取这些主机变量,我严重遗憾 ansible 的 Jinja2 中缺乏字典理解,但迭代版本
works

很好: - debug: msg: >- {%- set r = {} -%} {%- for hv in hostvars.keys() -%} {%- set d = {} -%} {%- for f in the_facts -%} {%- set _ = d.update({f: hostvars[hv][f]}) -%} {%- endfor -%} {%- set _ = r.update({hv: d}) -%} {%- endfor -%} {{ r }} vars: the_facts: - host_var_one - host_var_two



0
投票

ansible-inventory --list -i inventory/hosts.ini

它会输出整个库存树以及分配的变量。

此外,在与清单文件相同的目录级别中,您可以有一个名为

group_vars

的文件夹(这也是内置的预定义命名约定),它将保留每个主机或每个主机组的所有变量。 .. 请阅读手册中的更多内容

此处
.

© www.soinside.com 2019 - 2024. All rights reserved.