Ansible: объединить элементы элементов dict stdout_results в цикле - PullRequest
0 голосов
/ 12 сентября 2018

Я пытаюсь поддерживать шаблоны для фрагментов файла конфигурации nginx. Эти фрагменты я хочу применить к различным типам веб-серверов, где каждому серверу нужна только часть этих фрагментов. Мой подход (возможно, есть и лучший) заключался в создании подкаталогов для каждой группы хостов (например, proxy-node) и связывании необходимых файлов, поэтому мне нужно хранить шаблоны только в одном месте. Моя папка с шаблонами выглядит так:

    nginx.conf
    proxy-nodes
    ├── conf.d
    └── snippets
        ├── cors.conf -> ../../snippets/cors.conf
        ├── proxy_backend.conf -> ../../snippets/proxy_backend.conf
        ├── proxy_conditions.conf -> ../../snippets/proxy_conditions.conf
        ├── proxy_location_assets.conf -> ../../snippets/proxy_location_assets.conf
        ├── proxy_static_params.conf -> ../../snippets/proxy_static_params.conf
        └── ssl.conf -> ../../snippets/ssl.conf
    snippets
    ├── backend.conf
    ├── ban.conf
    ├── cors.conf
    ├── proxy_backend.conf
    ├── proxy_conditions.conf
    ├── proxy_location_assets.conf
    ├── proxy_static_params.conf
    └── ssl.conf

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

- name: create dict of group dirs with snippets files                                               
  shell: ls roles/nginx/templates/{{ item|quote }}/snippets/* | cut -d'/' -f4-
  register: nginx_group_dirs 
  delegate_to: localhost
  with_lines: for i in $(ls -d roles/nginx/templates/*/); do echo $i | cut -f4 -d'/'; done
  when: item in group_names

Это дает мне несколько элементов с файлами в nginx_group_dirs.results.item.stdout_lines:

"nginx_group_dirs": {
    "changed": true, 
    "msg": "All items completed", 
    "results": [
 ...
            },
            "item": "proxy-nodes", 
            "rc": 0, 
            "start": "2018-09-12 10:45:14.652846", 
            "stderr": "", 
            "stderr_lines": [], 
            "stdout": "proxy-nodes/snippets/backend.conf\nproxy-nodes/snippets/ban.conf\nproxy-nodes/snippets/cors.conf\nproxy-nodes/snippets/proxy_backend.conf\nproxy-nodes/snippets/proxy_conditions.conf\nproxy-nodes/snippets/proxy_location_assets.conf\nproxy-nodes/snippets/proxy_static_params.conf\nproxy-nodes/snippets/ssl.conf", 
            "stdout_lines": [
                "proxy-nodes/snippets/cors.conf", 
                "proxy-nodes/snippets/proxy_backend.conf", 
                "proxy-nodes/snippets/proxy_conditions.conf", 
                "proxy-nodes/snippets/proxy_location_assets.conf", 
                "proxy-nodes/snippets/proxy_static_params.conf", 
                "proxy-nodes/snippets/ssl.conf"
            ]
        }, 
        {
            "_ansible_ignore_errors": null, 
            "_ansible_item_label": "snippets", 
            "_ansible_item_result": true, 
            "_ansible_no_log": false, 
            "changed": false, 
            "item": "snippets", 
            "skip_reason": "Conditional result was False", 
            "skipped": true
        }, 

Позже я понял, что перечисление структуры каталогов только для совпадающих групповых имен приводит к тому, что некоторые элементы не имеют stdout_lines. Теперь моя проблема состоит в том, чтобы найти правильный цикл и / или синтаксис фильтра для шаблонирования всех соответствующих файлов stdout_lines из нескольких элементов.

- name: template snippets for all applicable groups
  template: 
    src: "{{ item }}"
    dest: "/etc/nginx/snippets/{{ item | basename }}"
    backup: yes
    with_items: "{{ nginx_group_dirs.results | map(attribute='stdout_lines') | list }}"
    when: item.stdout_lines is defined

Я добавил предложение when:, которое дает мне этот вывод (здесь больше элементов, потому что я не хочу расширять пост:

TASK [nginx : template snippets for all applicable groups] ********************************************
skipping: [eu-proxy1] => (item=[Undefined, Undefined, Undefined, [u'eu-proxy-nodes/sites-available/default'], [u'proxy-nodes/snippets/cors.conf', u'proxy-nodes/snippets/proxy_backend.conf', u'proxy-nodes/snippets/proxy_conditions.conf', u'proxy-nodes/snippets/proxy_location_assets.conf', u'proxy-nodes/snippets/proxy_static_params.conf', u'proxy-nodes/snippets/ssl.conf'], Undefined, Undefined]) 

Если я использую предложение techrafs без условия когда

with_items: "{{ nginx_group_dirs.results | map(attribute='stdout_lines') | flattened }}"

Я получаю (потому что у некоторых предметов нет 'stdout_lines'?):

fatal: [eu-proxy1]: FAILED! => {"msg": "'dict object' has no attribute 'stdout_lines'"}

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

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

Я нашел способ запустить шаблонизацию, но мне немного странно:

- name: create dict of group dirs with subdirs and files
  shell: ls -d1 roles/nginx/templates/{{ item|quote }}/*/* | cut -d'/' -f4- 
  register: nginx_group_dirs
  delegate_to: localhost
  with_lines: for i in $(ls -d roles/nginx/templates/*/); do echo $i | cut -f4 -d'/'; done
  when: item in group_names

- debug: msg="{{ item.stdout_lines | default([]) }}"
  register: file_list
  loop: "{{ nginx_group_dirs.results }}"

- name: template snippets for all applicable groups
  template: 
    src: "{{ item }}"
    dest: "/etc/nginx/{{ item | regex_replace('^(\\w(-?))+\\/', '') }}"
    backup: yes
  loop: "{{ file_list.results | map(attribute='msg') | flatten }}"
0 голосов
/ 12 сентября 2018

Ваш шаблон:

{{ nginx_group_dirs.results | map(attribute='stdout_lines') | list }}

создает список списков (stdout_lines).

Поскольку вы хотите перебрать элементы всех stdout_lines, вам нужно сгладитьВаш результат:

{{ nginx_group_dirs.results | map(attribute='stdout_lines') | flatten }}
...