Как объединить несколько переменных dict в массив на основе регулярного выражения имен переменных dict - PullRequest
0 голосов
/ 12 апреля 2019

В моих кадастрах есть несколько переменных dict, которые начинаются с 'my_var_ *'. Я хотел бы объединить их в массив dicts 'my_var'

В моей книге воспроизведения я использую set_fact: для создания переменной my_var, пытаясь извлечь совпадающие переменные из "hostvars ['localhost']" с помощью фильтра select и сопоставить регулярное выражение, но соединение работает только на струнах.

variables.yml

    my_var_1:
        element1: value11
        element2: value12
    my_var_2:
        element1: value21
        element2: value22

playbook.yml

    - hosts: localhost
      connection: local
      gather_facts: False
      tasks:
        - set_fact:
            my_var: "{{ hostvars['localhost'] | select('match', '^my_var_*') | join(', ' }}"
        - debug:
            msg: "{{ my_var }}"

возможно ли объединить эти переменные 'dict' в 'массив', подобный этому?

    my_var:
      - element1: value11
        element2: value12
      - element1: value21
        element2: value22

или, возможно, даже

    my_var:
      - name: 1
        element1: value11
        element2: value12
      - name: 2
        element1: value21
        element2: value22

1 Ответ

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

Вы очень близки, но, как вы заметили, метод join для строки предназначен для объединения строк.Вы хотите добавить списки, которые вы выполняете с помощью оператора +.

Есть также несколько других проблем:

Выражение:

hostvars['localhost'] | select('match', '^my_var_*')

Произведетсписок, который выглядит так:

[
  "my_var_1",
  "my_var_2"
]

... это не то, что вы хотите.Вы хотите значения этих переменных, а не имена ключей.Мы можем использовать фильтр dict2items и фильтр selectattr для генерации данных, которые нам нужны:

---
- hosts: localhost
  gather_facts: false
  tasks:
    - name: set facts on localhost
      set_fact:
        my_var_1:
            element1: value11
            element2: value12
        my_var_2:
            element1: value21
            element2: value22

- hosts: localhost
  gather_facts: false
  tasks:
    - name: merge vars into my_var
      set_fact:
        my_var: "{{ hostvars['localhost']|dict2items|selectattr('key', 'match', '^my_var_')|map(attribute='value')|list }}"

    - name: show content of my_var
      debug:
        var: my_var

Это даст следующий вывод:

TASK [show content of my_var] ************************************************************************************
ok: [localhost] => {
    "my_var": [
        {
            "element1": "value11", 
            "element2": "value12"
        }, 
        {
            "element1": "value21", 
            "element2": "value22"
        }
    ]
}

Если вы избавитесьфильтра map(attribute='value') вы получаете:

TASK [show content of my_var] *****************************************************************************************
ok: [localhost] => {
    "my_var": [
        {
            "key": "my_var_1", 
            "value": {
                "element1": "value11", 
                "element2": "value12"
            }
        }, 
        {
            "key": "my_var_2", 
            "value": {
                "element1": "value21", 
                "element2": "value22"
            }
        }
    ]
}

Это не совсем то, что вы запрашиваете в качестве второго варианта, но оно включает в себя как имя ключа, так и значения.


Дополнительные примечания:

  1. В приведенном выше примере я использовал отдельную игру, запускаемую set_fact, чтобы установить значения этих переменных, потому что это решение будет работать, только если переменныеявляются хост-переменными (то есть «фактами»), а не глобальными переменными.Вы не показываете в своем вопросе, как вы устанавливаете эти переменные, поэтому я не знаю, будет ли все это работать так, как написано.

  2. В регулярном выражении * означает«предыдущий символ ноль или более раз», поэтому выражение ^my_var_* будет соответствовать my_var, my_var_1, my_var______________, my_varfoo и так далее.Вы можете просто написать ^my_var_, чтобы выбрать имена переменных, которые вас интересуют (это выберет все, что начинается с текста my_var_).

...