Включая переменные из нескольких папок, добавляя имена папок к именам переменных

#ansible

Вопрос:

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

 containers
|_ deluge
  |_ defaults
    |_ main.yml
  |_ tasks
    |_ main.yml
|_ jellyfin
  |_ defaults
    |_ main.yml
  |_ tasks
    |_ main.yml
 

В каждой папке есть default/main.yml файл, который выглядит следующим образом:

 ---
container_name: deluge

port: 8112
homer_url: "http://{{ ansible_host }}:{{ port }}"
 

Эти переменные имеют одинаковые имена во всех папках.

Я хотел бы импортировать homer_url переменные в учебник в следующей форме, чтобы я мог обращаться к ним с помощью homer_containers.deluge , homer_containers.jellyfin , и так далее:

 homer_containers {
   deluge: "http://myhost.com:8112"
   plex: "http://myhost.com:32400"
   jellyfin: "http://myhost.com:8096"
}
 

Вот как я пытаюсь это сделать:

 ---
- name: Get a list of containers
  delegate_to: localhost
  become: no
  find:
    paths: 
      - "roles/containers"
    file_type: directory
    excludes: "homer"
    recurse: no
  register: containers

- name: Include all .json and .jsn files in vars/all and all nested directories (2.3)
  include_vars:
    dir: "{{ playbook_dir }}/{{ item.path }}/defaults"
    files_matching: main.yml
    name: "{{ item.path.split('/')[-1] }}"
  with_items: "{{ containers.files }}"
  no_log: true

- name: print out
  debug:
    var: deconz.homer_url

- name: Populate the dictionary
  set_fact:
    homer_containers: "{{ homer_containers | default({}) | combine ( { item.path.split('/')[-1] : vars[item.path.split('/')[-1]   '.homer_url'] } ) }}"
    cacheable: true
  with_items: "{{ containers.files }}"

- name: print out
  debug:
    var: homer_containers

 

Однако Ansible не удается преобразовать имя переменной в фактическую переменную:

 TASK [containers/homer : print out] 
ok: [myhost] => {
    "deconz.homer_url": "http://myhost.com:8085"
}

TASK [containers/homer : Populate the dictionary]
fatal: [myhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. 
The error was: 'dict object' has no attribute 'deconz.homer_url'}
 

Ответ №1:

Вместо того , чтобы обращаться к переменной как foo['bar.baz'] , так и должно быть foo['bar']['baz'] .

Так что просто изменитесь:

 vars[item.path.split('/')[-1]   '.homer_url']
 

Для

 vars[item.path.split('/')[-1]]['homer_url']
 

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

1. Это, казалось, сработало, однако переменные усов, похоже, не разрешаются внутри диктанта, например "bitwarden": "https://bitwarden.{{ host }}"

Ответ №2:

Ответ @Rickkwa сработал после небольшой корректировки. Я также изменил структуру, включив в нее другую переменную ( homer_category )

 - name: Populate the dictionary
  set_fact:
    homer_urls: "{{ homer_urls | default([])   [{ 'name': item.path.split('/')[-1], 'url' : lookup('vars', item.path.split('/')[-1])['homer_url'] | default(''), 'category': lookup('vars', item.path.split('/')[-1])['homer_category'] | default ('') }] }}"
  with_items: "{{ containers.files }}"