Return 来自 set_fact 的与 var 相同的数据
Return same data from set_fact as var
我正在尝试创建字典。使用 var 时一切正常。但是 Set_fact 好像有什么东西被忽略了,我无法隔离。
正在阅读 Jinja2 手册,多次迭代
---
- hosts: localbox gather_facts: false
vars:
app_servers: 5
ipaddress_base: "192.168.0"
rmi_portbase: 10000
host_info: |
{% set res = [] -%}
{%- for number in range(1,app_servers + 1) -%}
{% set ignored = res.extend([{
'hostname': 'app' + number|string,
'ipaddress': ipaddress_base + '.' + number|string,
'rmi_port': rmi_portbase|int + ( number * 10)
}]) -%}
{%- endfor %}
{{ res }}
tasks:
- name: thing
set_fact:
thing2: "{% set res = [] -%}
{%- for number in range(1,app_servers + 1) -%}
{% set ignored = res.extend([{
'hostname': 'app' + number|string,
'ipaddress': ipaddress_baase + '.' + number|string,
'rmi_port': rmi_portbase|int + ( number * 10)
}]) -%}
{%- endfor %}
{{ res }}"
- debug: var=host_info[0].hostname
- debug: var=thing2[0]
我希望从 thing2 得到像 host_info 这样的结果。
TASK [debug] *******************************************************************
ok: [localhost] => {
"host_info[0].hostname": "app1"
}
TASK [debug] *******************************************************************
ok: [localhost] => {
"thing2[0]": " "
}
如果您 运行 您发布的剧本,它应该会失败并出现以下错误:
TASK [thing]
fatal: [localhost]: FAILED! => {"msg": "The task includes an option
with an undefined variable. The error was: 'ipaddress_baase' is
undefined\n\nThe error appears to have been in '/home/lars/
tmp/ansible/playbook.yml': line 25, column 7, but may\nbe elsewhere in
the file depending on the exact syntax problem.\n\nThe offending line
appears to be:\n\n\n - name: thing\n ^ her e\n"}
事实上,您将 ipaddress_base
拼错为 ipaddress_baase
(注意多余的 a
)。如果您修复该拼写错误并添加修改最终的 debug
任务,如下所示:
- debug: var=thing2
您应该看到以下输出:
TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
"thing2": " [{'rmi_port': 10010, 'hostname': u'app1', 'ipaddress': u'192.168.0.1'}, {'rmi_port': 10020, 'hostname': u'app2', 'ipaddress': u'192.168.0.2'}, {'rmi_port': 10030, 'hostname': u'app3', 'ipaddress': u'192.168.0.3'}, {'rmi_port': 10040, 'hostname': u'app4', 'ipaddress': u'192.168.0.4'}, {'rmi_port': 10050, 'hostname': u'app5', 'ipaddress': u'192.168.0.5'}]"
}
向我们展示的是 thing2
是一个字符串,而不是字典。因此,当您为 thing2[0]
分配任务时,您将获得该字符串的 0
位置的字符。
原因它是一个字符串而不是字典是因为索引0处的前导space。我们可以通过将 endfor
语句中的终端标记从 %}
更改为 -%}
来修复它,这将吃掉任何以下 whitespace:
- set_fact:
thing2: "{% set res = [] -%}
{%- for number in range(1,app_servers + 1) -%}
{% set ignored = res.extend([{
'hostname': 'app' + number|string,
'ipaddress': ipaddress_baase + '.' + number|string,
'rmi_port': rmi_portbase|int + ( number * 10)
}]) -%}
{%- endfor -%}
{{ res }}"
有了这个和你原来的 debug
任务,我们看到输出:
TASK [set_fact] *******************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
"host_info[0].hostname": "app1"
}
TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
"thing2[0]": {
"hostname": "app1",
"ipaddress": "192.168.0.1",
"rmi_port": 10010
}
}
话虽如此,我会停止尝试使用这种技术来生成复杂的数据结构,因为正如我们所见,它很容易出错。我会这样写:
- set_fact:
thing2: "{{ thing2|default([]) + [{
'hostname': 'app' ~ item,
'ipaddress': ipaddress_base ~ '.' ~ item,
'rmi_port': rmi_portbase ~ (item * 10)}]
}}"
loop: "{{ range(1, app_servers+1)|list }}"
我认为这既易于实现又易于阅读。
我正在尝试创建字典。使用 var 时一切正常。但是 Set_fact 好像有什么东西被忽略了,我无法隔离。
正在阅读 Jinja2 手册,多次迭代
---
- hosts: localbox gather_facts: false
vars:
app_servers: 5
ipaddress_base: "192.168.0"
rmi_portbase: 10000
host_info: |
{% set res = [] -%}
{%- for number in range(1,app_servers + 1) -%}
{% set ignored = res.extend([{
'hostname': 'app' + number|string,
'ipaddress': ipaddress_base + '.' + number|string,
'rmi_port': rmi_portbase|int + ( number * 10)
}]) -%}
{%- endfor %}
{{ res }}
tasks:
- name: thing
set_fact:
thing2: "{% set res = [] -%}
{%- for number in range(1,app_servers + 1) -%}
{% set ignored = res.extend([{
'hostname': 'app' + number|string,
'ipaddress': ipaddress_baase + '.' + number|string,
'rmi_port': rmi_portbase|int + ( number * 10)
}]) -%}
{%- endfor %}
{{ res }}"
- debug: var=host_info[0].hostname
- debug: var=thing2[0]
我希望从 thing2 得到像 host_info 这样的结果。
TASK [debug] *******************************************************************
ok: [localhost] => {
"host_info[0].hostname": "app1"
}
TASK [debug] *******************************************************************
ok: [localhost] => {
"thing2[0]": " "
}
如果您 运行 您发布的剧本,它应该会失败并出现以下错误:
TASK [thing]
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ipaddress_baase' is undefined\n\nThe error appears to have been in '/home/lars/ tmp/ansible/playbook.yml': line 25, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: thing\n ^ her e\n"}
事实上,您将 ipaddress_base
拼错为 ipaddress_baase
(注意多余的 a
)。如果您修复该拼写错误并添加修改最终的 debug
任务,如下所示:
- debug: var=thing2
您应该看到以下输出:
TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
"thing2": " [{'rmi_port': 10010, 'hostname': u'app1', 'ipaddress': u'192.168.0.1'}, {'rmi_port': 10020, 'hostname': u'app2', 'ipaddress': u'192.168.0.2'}, {'rmi_port': 10030, 'hostname': u'app3', 'ipaddress': u'192.168.0.3'}, {'rmi_port': 10040, 'hostname': u'app4', 'ipaddress': u'192.168.0.4'}, {'rmi_port': 10050, 'hostname': u'app5', 'ipaddress': u'192.168.0.5'}]"
}
向我们展示的是 thing2
是一个字符串,而不是字典。因此,当您为 thing2[0]
分配任务时,您将获得该字符串的 0
位置的字符。
原因它是一个字符串而不是字典是因为索引0处的前导space。我们可以通过将 endfor
语句中的终端标记从 %}
更改为 -%}
来修复它,这将吃掉任何以下 whitespace:
- set_fact:
thing2: "{% set res = [] -%}
{%- for number in range(1,app_servers + 1) -%}
{% set ignored = res.extend([{
'hostname': 'app' + number|string,
'ipaddress': ipaddress_baase + '.' + number|string,
'rmi_port': rmi_portbase|int + ( number * 10)
}]) -%}
{%- endfor -%}
{{ res }}"
有了这个和你原来的 debug
任务,我们看到输出:
TASK [set_fact] *******************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
"host_info[0].hostname": "app1"
}
TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
"thing2[0]": {
"hostname": "app1",
"ipaddress": "192.168.0.1",
"rmi_port": 10010
}
}
话虽如此,我会停止尝试使用这种技术来生成复杂的数据结构,因为正如我们所见,它很容易出错。我会这样写:
- set_fact:
thing2: "{{ thing2|default([]) + [{
'hostname': 'app' ~ item,
'ipaddress': ipaddress_base ~ '.' ~ item,
'rmi_port': rmi_portbase ~ (item * 10)}]
}}"
loop: "{{ range(1, app_servers+1)|list }}"
我认为这既易于实现又易于阅读。