ansible вложен цикъл fileglob ansible речник with_nested

да предположим, че имам следното дърво:

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

Не знам какви са файловете и колко от тях има в directory_1 и directory_2, искам да мога да влизам в тях и да ги изброявам.

Имам следния ansible dict:

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

но не мога да го накарам да работи, за ansible списъкът е празен, опитах:

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

но все още списъкът е празен, какво правя погрешно? възможно ли е да се постигне този вид изход, като се използва само ansible? няма 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 в цикъл, за да разберете структурата на тази променлива.

В задачата за показване на резултатите ние итерираме резултата от първия цикъл, използвайки subelements филтър. Това на практика ни дава сплескан списък от (directory, file_path) кортежи, така че можем да генерираме изхода, който търсите.

С вашата примерна файлова структура, изпълнението на горната книга за игра дава следния резултат:


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