L oop не повторяется по последней строке списка - PullRequest
0 голосов
/ 29 мая 2020

Я создал шаблон в playbook, который я хочу перебрать со списком хэшей. Результат этого я хочу добавить в другую переменную для использования в следующем модуле.

Шаблон работает, и l oop выглядит так, как будто он работает, но он никогда не добавляет последний элемент в списке. Я воссоздал его в тестовой игре.

---
- hosts: localhost
  tasks:
  - name: Init
    set_fact:
      foo: []
      fqdn: "test.com"
      template: []

  - name: portlist
    set_fact:
      portlist:
      - { port: 9091, index: 1 }
      - { port: 9092, index: 2 }
      - { port: 9093, index: 3 }
      - { port: 9094, index: 4 }

  - name: generate policy
    set_fact:
      template:
      - name: "traffic to {{ item.port }}"
        index: "{{ item.index }}"
        match:
          desc: "[{{ item.port }}]" # The field needs to be passed as a list
          name: "{{ fqdn }}_{{ item.port }}"
          port: "{{ item.port }}"
      foo: "{{ foo + template }}"
    loop: "{{ portlist }}"

  - debug:
      var: foo

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

Результаты игры в списке хэшей, которые затем я могу ввести в модуль политики. Однако он дает мне только 3 элемента в списке и пропускает последний элемент в списке портов.

TASK [debug] ***************************************************
ok: [localhost] => {
    "foo": [
        {
            "action": {
                "ref": "test.com_9091",
                "this": true
            },
            "enable": true,
            "index": "1",
            "match": {
                "port": {
                    "criteria": "IS_IN",
                    "port": [
                        9091
                    ]
                }
            },
            "name": "traffic to 9091"
        },
        {
            "action": {
                "ref": "test.com_9092",
                "this": true
            },
            "enable": true,
            "index": "2",
            "match": {
                "port": {
                    "criteria": "IS_IN",
                    "port": [
                        9092
                    ]
                }
            },
            "name": "traffic to 9092"
        },
        {
            "action": {
                "ref": "test.com_9093",
                "this": true
            },
            "enable": true,
            "index": "3",
            "match": {
                "port": {
                    "criteria": "IS_IN",
                    "port": [
                        9093
                    ]
                }
            },
            "name": "traffic to 9093"
        }
    ]
}

1 Ответ

1 голос
/ 29 мая 2020

Ваша проблема вызвана тем, что переменные, определенные через set_fact, недоступны до тех пор, пока не будет завершена задача set_fact. Это означает, что когда вы устанавливаете:

foo: "{{ foo + template }}"

, вы видите значение template из предыдущей итерации l oop.

Один из способов справиться с этим - переписать вашу set_fact задачу, чтобы установить foo напрямую:

---
- hosts: localhost
  gather_facts: false
  vars:
    fqdn: "test.com"
    portlist:
      - {port: 9091, index: 1}
      - {port: 9092, index: 2}
      - {port: 9093, index: 3}
      - {port: 9094, index: 4}
  tasks:
    - name: generate policy
      set_fact:
        foo: >-
          {{
            foo + [{
              'name': 'traffic to {}'.format(item.port),
              'index': item.index,
              'match': {
                'desc': "[{}]".format(item.port),
                'name': '{}_{}'.format(fqdn, item.port),
                'port': item.port
              }
            }]
          }}
      vars:
        foo: []
      loop: "{{ portlist }}"

    - debug:
        var: foo

Это выведет:

TASK [debug] *********************************************************************************************************************************************************************************
ok: [localhost] => {
    "foo": [
        {
            "index": 1,
            "match": {
                "desc": "[9091]",
                "name": "test.com_9091",
                "port": 9091
            },
            "name": "traffic to 9091"
        },
        {
            "index": 2,
            "match": {
                "desc": "[9092]",
                "name": "test.com_9092",
                "port": 9092
            },
            "name": "traffic to 9092"
        },
        {
            "index": 3,
            "match": {
                "desc": "[9093]",
                "name": "test.com_9093",
                "port": 9093
            },
            "name": "traffic to 9093"
        },
        {
            "index": 4,
            "match": {
                "desc": "[9094]",
                "name": "test.com_9094",
                "port": 9094
            },
            "name": "traffic to 9094"
        }
    ]
}

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

---
- hosts: localhost
  gather_facts: false
  vars:
    fqdn: "test.com"
    portlist:
      - {port: 9091, index: 1}
      - {port: 9092, index: 2}
      - {port: 9093, index: 3}
      - {port: 9094, index: 4}
  tasks:
  - name: generate policy
    set_fact:
      template:
        name: "traffic to {{ item.port }}"
        index: "{{ item.index }}"
        match:
          desc: "[{{ item.port }}]" # The field needs to be passed as a list
          name: "{{ fqdn }}_{{ item.port }}"
          port: "{{ item.port }}"
    loop: "{{ portlist }}"
    register: foo

  - set_fact:
      foo: "{{ foo.results | map(attribute='ansible_facts.template') | list }}"

  - debug:
      var: foo
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...