Вернуть те же данные из set_fact как var - PullRequest
0 голосов
/ 23 апреля 2019

Я пытаюсь создать словарь. При использовании 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]

Я ожидаю результатов вроде host_info от thing2.

TASK [debug] *******************************************************************
ok: [localhost] => {
    "host_info[0].hostname": "app1"
}

TASK [debug] *******************************************************************
ok: [localhost] => {
    "thing2[0]": " "
}

1 Ответ

1 голос
/ 23 апреля 2019

Если вы запустили опубликованную пьесу, она должна завершиться ошибкой:

ЗАДАЧА [вещь]


фатально: [localhost]: СБОЙ! => {"msg": "Задача включает опцию с неопределенной переменной. Ошибка была: «ipaddress_baase» является undefined \ n \ nОшибка, по-видимому, была в '/ home / lars / tmp / ansible / playbook.yml ': строка 25, столбец 7, но может быть в другом месте файл в зависимости от точной синтаксической проблемы. \ n \ nОстранная строка похоже: \ n \ n \ n - имя: вещь \ n ^ ее 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 }}"

Я думаю, что и проще, и легче читать.

...