从set_fact返回与var相同的数据

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

我正在尝试创建一本字典。使用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]": " "
}
ansible jinja2 ansible-facts
1个回答
1
投票

如果您运行已发布的playbook,它将失败并显示以下错误:

任务[事物]


致命:[localhost]:失败! => {“msg”:“任务包含一个带有未定义变量的选项。错误是:'ipaddress_baase'未定义\ n \ n错误似乎出现在'/ home / lars / tmp / ansible / playbook.yml中':第25行,第7列,但可能在文件的其他位置,具体取决于确切的语法问题。\ n \ n违规行似乎是:\ n \ n \ n - 名称: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处的前导空格。我们可以通过将endfor语句中的终端标记从%}更改为-%}来修复它,这会占用以下任何空格:

- 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 }}"

我认为这既易于实现又更易于阅读。

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