Ansible: невозможно пройти через переменную в модуле blockinfile

Я изо всех сил пытаюсь получить правильный вывод элементов в этой книге:

---
- hosts: host1 
  gather_facts: no
  vars_files: ~./secret.txt
  tasks:
  - ngine_io.cloudstack.cs_instance_info:
      api_key: "{{ key }}"
      api_url: "{{ endpoint }}"
      api_secret: "{{ secret }}"
    register: zones
  - set_fact:
      nic_info: "{{ zones.instances|sum(attribute='nic', start=[]) | list }}"
  - set_fact:
      vlan: "{{ nic_info | selectattr('network','defined') | map(attribute='network') | list | unique | split }}"
  - name: Create file
    blockinfile:
      path: /test/vlans.txt
      block: |
        interfaces:
         - num:
           - name: {{ item.0 }}
             egr: 10000
           - name: {{ item.1 }}
             egr: 10001"
      marker: "## {mark}  {{ item }}"
    delegate_to: localhost
    with_items: "{{ vlan }}"

Когда я использую этот, я получаю следующий вывод в текстовом файле:

## BEGIN  vlan://100

interfaces:
 - num:
   - name: v
     egr: 10000
   - name: l
     egr: 10001"
## END  vlan://100
## BEGIN  vlan://101
interfaces:
 - num:
   - name: v
     egr: 10000
   - name: l
     egr:10001"
## END  vlan://101

Однако, когда я отлаживаю его с помощью «var: vlan.0», я получаю правильный вывод:

  - debug:
      msg: "{{ vlan.0 }}"

Получил этот вывод:

ok: [host1] => {
    "msg": "vlan://100"
}

Отладка переменной vlan:

"msg": [
        "vlan://100",
        "vlan://101"
    ]

Кто-нибудь, чтобы сказать мне, что я делаю неправильно здесь? Спасибо.

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

## BEGIN  vlan://100
"interfaces:
 - num:
   - name: 'vlan://100'
     egr: 10000
   - name: 'vlan://100'
     egr: 10001"
## END  vlan://100
## BEGIN  vlan://101
"interfaces:
 - num:
   - name: 'vlan://101'
     egr: 10000
   - name: 'vlan://101'
     egr: 10001"
## END  vlan://101

Однако то, что я хотел бы получить, это:

## BEGIN  vlan://101
"interfaces:
 - num:
   - name: 'vlan://100'
     egr: 10000
   - name: 'vlan://101'
     egr: 10001"
## END  vlan://101

Ваш вывод отладки выводит всю строку, потому что вы сравниваете разные вещи: вы сравниваете {{ vlan.0 }} (первый элемент из списка vlan) с {{ item.0 }} (первый символ строки, хранящейся в item).

larsks 10.11.2022 14:22

Я обновил свой ответ, чтобы получить желаемый результат.

larsks 10.11.2022 14:22
Введение в Ansible Roles
Введение в Ansible Roles
Ansible - это отличный инструмент управления конфигурацией, который можно использовать для автоматизации настройки или развертывания на большом...
0
2
74
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Обновлять

Для желаемого результата не имеет смысла повторять задачу по списку vlan, потому что вам нужен только один блок. Вместо этого вам нужно будет использовать шаблон в содержимом блока, например:

- hosts: localhost
  gather_facts: false
  vars:
    vlan:
      - vlan://100
      - vlan://101

  tasks:
    - name: Create file
      blockinfile:
        path: vlans.txt
        block: |
          interfaces:
            - num:
              {% for item in vlan -%}
              - name: {{ item }}
                egr: {{ (item.split('//')[1])|int + 9900 }}
              {% endfor %}
        marker: "## {mark} vlans"
      delegate_to: localhost

Это приведет к:

## BEGIN vlans
interfaces:
  - num:
    - name: vlan://100
      egr: 10000
    - name: vlan://101
      egr: 10001
    
## END vlans

Мне пришлось добавить немного странный расчет, чтобы получить значение egr, поскольку вы, казалось, ожидали, что это изменится вместе с vlan.


Оригинальный ответ

Переменная vlan, основанная на результатах отладки, представляет собой список строк:

"msg": [
        "vlan://100",
        "vlan://101"
    ]

Это означает, что когда вы повторяете vlan в своей blockinfile задаче, item будет принимать значения последовательных элементов из списка vlan.

Другими словами, во время первой итерации item будет vlan://100. Поскольку мы это знаем, неудивительно, что {{ item.0 }} приводит к v: мы запросили первый символ строки vlan://100.

Это означает, что мы, вероятно, хотим:

  - name: Create file
    blockinfile:
      path: /test/vlans.txt
      block: |
        interfaces:
         - num:
           - name: {{ item }}
             egr: 10000
           - name: {{ item }}
             egr: 10001"
      marker: "## {mark}  {{ item }}"
    delegate_to: localhost
    with_items: "{{ vlan }}"

Но похоже, что вы уже поняли правильное решение:

Я также пытался запустить его без добавления индексов в конце, но тогда я получаю ожидаемый результат...

Привет, извините, я отредактировал свой вопрос, так как это был ожидаемый результат, но не тот, который я хотел. Я хотел бы преобразовать каждую строку в один список, чтобы я мог перебирать каждую из них. Чего я не понимаю, так это того, что при отладке vlan.0 я получаю правильный результат (vlan:100), а не первую букву....

Junk 10.11.2022 14:09

Я думаю, что у вас есть ошибка в вашей debug задаче, но, поскольку вы не опубликовали ни задачу, ни соответствующий вывод, трудно сказать. Может быть, обновить свой вопрос, чтобы включить эту информацию?

larsks 10.11.2022 14:12

Правильно, я отредактировал вопрос, я получаю правильный vlan100 при отладке с помощью «vlan.0», и это меня очень смущает.

Junk 10.11.2022 14:17

Рад помочь! Если это решило ваш вопрос, рассмотрите возможность установки галочки слева от этого ответа, чтобы отметить его как принятый.

larsks 10.11.2022 14:28

Другие вопросы по теме