LINUX.ORG.RU

Получить список субдиректорий, распарсить имена и использовать в качестве переменных

 


0

1

Привет, ЛОРчик!

Подскажи, как действовать, плес. Есть список директорий в /home/user/test_dir

/home/user/test_01
/home/user/test_2
/home/user/test_30
/home/user/blabla
/home/user/blabla1

Задача состоит в том, чтобы из test_1 взять только 1 и потом её где-то там дальше использовать.

Получить список директорий могу вот так

- name: test
  hosts: all
  tasks:
    - name: get dir names
      find:
        paths: /home/user/test_dir
        file_type: directory
        use_regex: yes
        patterns:'.*(?!test_)[0-9]+'
      register: dir_list

   -debug:
        msg: "{{ item.path }}"
    with_items: "{{ dir_list.files }}"

Пробема тут в том, что дебак выводит в msg полный путь path, а не последний цифры в имени директории test_01. и как это самое test_01 потом парсить, штоп 01 извлечь? Точнее гвооря, как вытаскивать 01 то я знаю, а как оперировать с перемнной в ансибле -нет

Кстати, как вообще просто вывести список директорий, прошедших через регэксп?

Прошу не гнать ссаными тряпками, потому как ансибл я толькл-только постигаю.

★★★

Последнее исправление: SpaceRanger (всего исправлений: 3)

Главный вопрос: а зачем? Я вот ни одного кейса не могу вспомнить, когда мне требовалось что-то подобное.

Если оно не в целях поиграться, а прямо какую-то реальную ситуацию моделирует, то первое, что приходит в голову, обрабатывать результаты с regex_search / regex_replace и т.п. Если не подходит, то написать кастомный фильтр на питоне.

Если нельзя что-то распарсить с помощью фильтров jinja, самый простой путь – написать свой фильтр и юзать его в таске.

Но я бы советовал посмотреть на задачу с другой стороны: может, имеет смысл не парсить какие-то случайные директории, а иметь список нужных и с ним работать? Сопоставлять его с результатами поиска, например.

Ансибл в принципе нужен для того, чтобы привести сервер в какое-то желааемое состояние, это состояние и описывается пошагово в тасках.

Для того, чтобы разгребать уже существующий бардак на диске, скорее всего подойдёт какой-то другой инструмент.

Ну и в 2023 году with_items не нужен, есть же loop.

ivanov17
()
Ответ на: комментарий от FireFighter

Нужно зайти на набор хостов и там заменить файлы всякие. Однако, в зависимости от названия папки, сделать некоторые модификации в этих самых файлах.

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

dirname:
  - test_1
    ports:
      - 1201
      - 5601
  - test_2
    ports:
      - 1202
      - 5602
  - test_3
    ports:
      - 1203
      - 5603
  - test_4
    ports:
      - 1204
      - 5604
  - test_5
    ports:
      - 1205
      - 5605

Теперь мне нужно как то этим добром модифицировать файл (свой для каждой директории).

port {{ testX.ports.0 }}
port {{ testX.ports.1 }}

super_puper_service /bin/system/{{ testX }}/start

И потом этот файл закинуть уже на управляемый хост. Но это вроде как просто.

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

Может ансибл и не совсем для этого подходит, но я хочу им научиться махать.

SpaceRanger ★★★
() автор топика
Последнее исправление: SpaceRanger (всего исправлений: 1)
Ответ на: комментарий от SpaceRanger

Это наверняка возможно, но я пока что не знаю как

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_filters.html

Собственно, умение махать ансиблом сводится к тому, чтобы свободно ориентироваться в его модулях и фильтрах jinja. Ну и помнить про variable precedence.

Другое дело, что завязываться на какие-то сторонние данные выглядит в принципе так себе. Хуже выглядят только динамические инвентори. Возникает вопрос почему эти данные нельзя определить сразу. Чтобы не чекать порты, а открывать их там, где нужно.

В принципе, в group_vars может лежать один список для группы хостов, из которого фильтрами можно дальше накручивать всё, что угодно для кучи разных ролей.

ivanov17
()
Ответ на: комментарий от ivanov17

я от природы туповат и чёт не могу сообразить как вары мои в шаблон пихать. Намекни хотяб, ссылку чекал - ничего особо не вынес для себя (может не туда смотрел)

SpaceRanger ★★★
() автор топика
Ответ на: комментарий от SpaceRanger

Держу в курсе происходящего. Возможно кому-то будет полезно, а может кто и укажэет на корявость решения.

Кароч, пока получилось вот так.

---
- name: update config
  hosts: all
  vars_files:
    - "vars/virtual_observer"
  tasks:
    - name: trying the same in shell
      shell:
         cd /home/observer/test_ansible; ls | grep -E "test_[0-9]+"
      register: out

    - debug: var=out.stdout_lines
      register: foo_result

    - name: the final result
      debug: var=foo_result

    - name: copy output to a file
      local_action:
        module: copy
        content: "{{ out.stdout_lines }}"
        dest: "{{ playbook_dir }}/{{ inventory_hostname }}"

    - name: update local var file
      delegate_to: localhost
      local_action: command python main.py "{{ inventory_hostname }}"

    - name: delete temporary config file
      delegate_to: localhost
      file:
        path: "{{ playbook_dir }}/{{ inventory_hostname }}"
        state: absent

    - name: test lookup
      debug:
        msg: "Host is {{ item.name }}, port1 is {{ item.port1 }} and port2 is {{ item.port2 }}"
      loop: "{{ namehost }}"

    - name: templating
      template:
        src: sys.config.j2
        dest: "/home/observer/test_ansible/{{ item.name }}/sys.config"
      loop: "{{ namehost }}"

Соответственно, файлик, который я создаю (типа вроде как переменные)

namehost:
  - name: test_1
    port1: 1201
    port2: 5601
  - name: test_2
    port1: 1202
    port2: 5602
  - name: test_3
    port1: 1203
    port2: 5603
  - name: test_4
    port1: 1204
    port2: 5604
  - name: test_5
    port1: 1205
    port2: 5605

Ну и шаблон Jinja для тестовых целей совсем простенький

This one goes to {{inventory_hostname}}
{{item.name}}
{{item.port1}}
{{item.port2}}

Пока что вопрос один - до того, как у меня отработает первая таска, никакого файла в vars_files у меня нет и вылетает с ошибкой об этом печальном факте. Подскажите, как этот филе создавать и чекать в процесе выполнения.

Так же хочу поплакаться об отстойности документации по ансиблу даже на официальном сайте.

Заранее высылаю лучи токсичной маскулинности

SpaceRanger ★★★
() автор топика
Последнее исправление: SpaceRanger (всего исправлений: 2)
---
- name: update config
  hosts: all 
  vars: 
    names: "{{ out.files|map(attribute='path')|map('basename')|list}}"  
  tasks:
    - name: get list of existing instances
      find:
        paths: /home/user
        file_type: directory
        use_regex: yes 
        patterns: "test_\\d+"
      register: out 

    - debug: var=names


    - name: copy output to a file
      local_action:
        module: copy
        content: "{{ out.stdout_lines }}"
        dest: "{{ playbook_dir }}/{{ inventory_hostname }}"

    - name: update local var file
      delegate_to: localhost
      local_action: command python main.py "{{ inventory_hostname }}"

    - name: delete temporary config file
      delegate_to: localhost
      file:
        path: "{{ playbook_dir }}/{{ inventory_hostname }}"
        state: absent

    - name: include VARS for each host 
      include_vars:
        file: "vars/{{ inventory_hostname }}"
        name: hui 

    - name: what is type
      debug:
        msg: "{{ hui | type_debug }}"

    - name: test lookup
      debug: 
        msg: "Host is {{ item.key }}, port1 is {{ item.value.port1 }} and port2 is {{ item.value.port2 }}"
      loop: "{{ lookup('dict', hui.namehost) }}"

    - name: templating
      template:
        src: sys.config.j2
        dest: "/home/user/{{ item.key }}/sys.config"
      loop: "{{ lookup('dict', hui.namehost) }}"

    - name: copy nt-adec to target hosts 
      copy:
        src: nt-adec.bin
        dest: "/home/user/{{ item.key }}/pipe"
        owner: user
        group: user
        mode: '755'                                                                                                                                       
      loop: "{{ lookup('dict', hui.namehost )}}"
namehost:
  test_1:
    port1: 1201
    port2: 5601
  test_10:
    port1: 12010
    port2: 56010
  test_2:
    port1: 1202
    port2: 5602
  test_3:
    port1: 1203
    port2: 5603
  test_4:
    port1: 1204
    port2: 5604
  test_5:
    port1: 1205
    port2: 5605
  test_6:
    port1: 1206
    port2: 5606
  test_7:
    port1: 1207
    port2: 5607
  test_8:
    port1: 1208
    port2: 5608
  test_9:
    port1: 1209
    port2: 5609

Кароч, вот готовое решение. Всем спасибо.

SpaceRanger ★★★
() автор топика
Последнее исправление: SpaceRanger (всего исправлений: 3)