Ansible jinja2 управляет списками на основе многоуровневых значений

#ansible #jinja2 #ansible-template

Вопрос:

Я пытаюсь манипулировать этим списком в Ansible:

 webserver:
  sites:
    - user: userone
      domains:
        - domain: domainone.com
        - domain: domaintwo.com
    - user: usertwo
      domains:
        - domain: domainthree.com
    - user: userthree
      domains:
        - domain: domainfour.com
        - domain: domainfive.com
 

В это:

 domains_with_user:
  - domain: domainone.com
    user: userone
  - domain: domaintwo.com
    user: userone
  - domain: domainthree.com
    user: usertwo
  - domain: domainfour.com
    user: userthree
  - domain: domainfive.com
    user: userthree
 

Но затем с кодом, основанным только на первой конфигурации «веб-сервер:».

Как я могу это сделать? Я бы предпочел сделать это как объявление новой переменной («domains_with_user»: {{ некоторый код }})

Ответ №1:

Вы можете использовать цикл с подэлементами фильтра

 ---
- hosts: localhost
  gather_facts: false

  vars:
    webserver:
      sites:
        - user: userone
          domains:
            - domain: domainone.com
            - domain: domaintwo.com
        - user: usertwo
          domains:
            - domain: domainthree.com
        - user: userthree
          domains:
            - domain: domainfour.com
            - domain: domainfive.com

  tasks:
    - name: Set domains_with_user variable
      set_fact:
        domains_with_user: "{{ domains_with_user | default([])   [{ 'domain': item.1.domain , 'user': item.0.user }] }}"
      loop: "{{ webserver.sites | subelements('domains') }}"

    - name: DEBUG
      debug:
        msg: "{{ domains_with_user }}"
 

и результат:

 PLAY [localhost] **********************************************************************************

TASK [Set domains_with_user variable] *************************************************************
ok: [localhost] => (item=[{'user': 'userone', 'domains': [{'domain': 'domainone.com'}, {'domain': 'domaintwo.com'}]}, {'domain': 'domainone.com'}])
ok: [localhost] => (item=[{'user': 'userone', 'domains': [{'domain': 'domainone.com'}, {'domain': 'domaintwo.com'}]}, {'domain': 'domaintwo.com'}])
ok: [localhost] => (item=[{'user': 'usertwo', 'domains': [{'domain': 'domainthree.com'}]}, {'domain': 'domainthree.com'}])
ok: [localhost] => (item=[{'user': 'userthree', 'domains': [{'domain': 'domainfour.com'}, {'domain': 'domainfive.com'}]}, {'domain': 'domainfour.com'}])
ok: [localhost] => (item=[{'user': 'userthree', 'domains': [{'domain': 'domainfour.com'}, {'domain': 'domainfive.com'}]}, {'domain': 'domainfive.com'}])

TASK [DEBUG] **************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "domain": "domainone.com",
            "user": "userone"
        },
        {
            "domain": "domaintwo.com",
            "user": "userone"
        },
        {
            "domain": "domainthree.com",
            "user": "usertwo"
        },
        {
            "domain": "domainfour.com",
            "user": "userthree"
        },
        {
            "domain": "domainfive.com",
            "user": "userthree"
        }
    ]
}

PLAY RECAP ****************************************************************************************
 

Комментарии:

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