доступный вложенный цикл fileglob доступный словарь with_nested

Предположим, у меня есть следующее дерево:

foo/
├─ bar/
│  ├─ secret/
│  │  ├─ directory_1/
│  │  │  ├─ file1
│  │  │  ├─ file2
│  │  ├─ directory_2/
│  │  │  ├─ file3
│  │  │  ├─ file4

Я не знаю, что это за файлы и сколько их внутри directory_1 и directory_2. Я хочу иметь возможность зацикливаться внутри них и перечислять их.

У меня есть следующий доступный диктат:

my_directory_list:
  var1: secret_dir
  file:
    - directory: directory_1
      secret_name: secret_1
    - directory: directory_2
      secret_name: secret_2

и следующая задача:

- name: "my task"
  shell: echo ' in my directory : {{item.0.directory}} i have {{item.1}} '
  with_nested:
    - "{{my_root_directory.file}}"
    - "{{ lookup('fileglob', '/foo/bar/secret/{{item.0.directory}}') }}"

и ожидаемый результат:

in my directory directory_1 i have file1
in my directory directory_1 i have file2
in my directory directory_2 i have file3
in my directory directory_2 i have file4

но я не могу заставить его работать, потому что список пуст, я пробовал:

- "{{ lookup('fileglob', '/foo/bar/secret/{{item.0.directory}}').split(',') }}"

но список все еще пуст, что я делаю не так? Можно ли добиться такого вывода, используя только анзибль? нет jinja / python?

Спасибо за помощь,


person Omar BISTAMI    schedule 18.04.2021    source источник


Ответы (1)


Во-первых, в вашей книге есть несколько синтаксических ошибок, которые не позволят запустить ее вообще.

Ошибки цитирования

Если вы используете кавычки в значении YAML, вы должны заключить в кавычки все. Итак, когда вы пишете:

- name: "my task"
  shell: echo ' in my directory : {{item.0.directory}} i have {{item.1}} '

Это значение ключа shell: вызовет ошибку:

ERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each:
JSON: Expecting value: line 1 column 1 (char 0)

Syntax Error while loading YAML.
  mapping values are not allowed in this context

Вам нужно заключить все значение в кавычки, например:

- name: "my task"
  shell: "echo ' in my directory : {{item.0.directory}} i have {{item.1}} '"

Я предпочитаю использовать один из операторов блочных кавычек YAML, например:

- name: "my task"
  shell: >-
    echo ' in my directory : {{item.0.directory}} i have {{item.1}} '

Это позволяет избежать необходимости играть в игры с экранированием кавычек, если вам нужно использовать как двойные, так и одинарные кавычки в командной строке.

Ошибки подстановки переменных

Вы никогда не вкладываете маркеры шаблона Jinja ({{...}}). Когда вы пишете:

- "{{ lookup('fileglob', '/foo/bar/secret/{{item.0.directory}}') }}"

В итоге вы передаете буквальную строку /foo/bar/secret/{{item.0.directory}} поиску fileglob. Вместо этого вам нужно будет написать это так:

- "{{ lookup('fileglob', '/foo/bar/secret/' ~ item.0.directory) }}"

Где ~ - оператор конкатенации строк Jinja. Но это все равно не сработает, потому что ...

Логические ошибки

Переменная цикла item недоступна в аргументах для with_nested (поскольку цикл еще не начал выполняться, когда аргументы интерпретируются), поэтому даже если вы исправите синтаксис, вы увидите следующую ошибку:

TASK [my task] *******************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "'item' is undefined"}

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

- hosts: localhost
  gather_facts: false
  vars:
    my_directory_list:
      var1: secret_dir
      file:
        - directory: directory_1
          secret_name: secret_1
        - directory: directory_2
          secret_name: secret_2

  tasks:
    - name: "find files"
      find:
        path: "foo/bar/secret/{{ item.directory }}"
      register: files
      loop: "{{ my_directory_list.file }}"

    - name: "display results"
      debug:
        msg: "In my directory {{ item.0.item.directory }} I have {{ item.1.path|basename }}"
      loop: "{{ files.results|subelements('files') }}"
      loop_control:
        label: "{{ item.1.path }}"

В приведенном выше сборнике задач задача поиска файлов использует модуль find для получения списка файлов в каждом каталоге, указанном в my_directory_list.files. Регистрируем результаты этого цикла в переменной files. См. документацию по использованию register в цикле, чтобы понять структуру этой переменной.

В задаче отображения результатов мы перебираем результат первого цикла, используя _ 20_ filter. Это фактически дает нам сплющенный список из (directory, file_path) кортежей, так что мы можем сгенерировать результат, который вы ищете.

С вашей примерной файловой структурой запуск вышеуказанного playbook дает следующий результат:


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

TASK [find files] ****************************************************************************************************************************************************************************
ok: [localhost] => (item={'directory': 'directory_1', 'secret_name': 'secret_1'})
ok: [localhost] => (item={'directory': 'directory_2', 'secret_name': 'secret_2'})

TASK [display results] ***********************************************************************************************************************************************************************
ok: [localhost] => (item=foo/bar/secret/directory_1/file2) => {
    "msg": "In my directory directory_1 I have file2"
}
ok: [localhost] => (item=foo/bar/secret/directory_1/file1) => {
    "msg": "In my directory directory_1 I have file1"
}
ok: [localhost] => (item=foo/bar/secret/directory_2/file4) => {
    "msg": "In my directory directory_2 I have file4"
}
ok: [localhost] => (item=foo/bar/secret/directory_2/file3) => {
    "msg": "In my directory directory_2 I have file3"
}

PLAY RECAP ***********************************************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

person larsks    schedule 18.04.2021
comment
спасибо за ответ, мне нужно будет запустить какой-то секрет kubectl для файлов по папкам, но я думаю, что понимаю вашу логику, и да, вы правы в отношении логической проблемы, я думал то же самое .. проверка и будет подтверждена, как только я получу домой, ты снова - person Omar BISTAMI; 18.04.2021