Поиск имени файла в разделе файлов текущей роли Ansible

Я новичок в Ansible, и я пытаюсь создать роль, которая копирует файл на удаленный сервер. Локальный файл может иметь другое имя при каждом запуске playbook, но его нужно скопировать на одно и то же имя удаленно, примерно так:

- name: copy file
  copy:
    src=*.txt
    dest=/path/to/fixedname.txt

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

- name: find the filename
    connection: local
    shell: "ls -1 files/*.txt"
    register: myfile

- name: copy file
  copy:
    src="files/{{ item }}"
    dest=/path/to/fixedname.txt
  with_items:
   - myfile.stdout_lines

Однако, когда я переместил задачи в роль, первое действие больше не работало, потому что относительный путь относится к роли, когда playbook выполняется в корневом каталоге каталога "role". Я мог бы добавить путь к файлу файлов ролей, но есть ли более элегантный способ?

Ответ 1

Похоже, вам нужен доступ к задаче, которая ищет информацию локально, а затем использует эту информацию в качестве ввода в модуль копирования.

Существует два способа получить локальную информацию.

  • используйте local_action:. Это сокращение для запуска задачи снова 127.0.0.1, более подробная информация найдена здесь. (это то, что вы использовали)

  • используйте lookup. Это плагиновая система, специально разработанная для получения информации локально. Подробнее здесь.

В вашем случае я бы пошел на второй метод, используя lookup. Вы можете настроить его следующим образом :

vars:
  local_file_name: "{{ lookup('pipe', 'ls -1 files/*.txt') }}"

tasks:
  - name: copy file
    copy: src="{{ local_file_name }}" dest=/path/to/fixedname.txt    

Или, более прямо:

tasks:
  - name: copy file
    copy: src="{{ lookup('pipe', 'ls -1 files/*.txt') }}" dest=/path/to/fixedname.txt    

Что касается путей

плагин lookup запускается из контекста задачи (playbook vs role). Это означает, что он будет вести себя по-разному в зависимости от того, где он использовался.

В приведенной выше настройке задачи запускаются непосредственно из учебника, поэтому рабочий каталог будет выглядеть следующим образом:

/path/to/project - это папка, в которой находится ваша тетрадь.

Если вы хотите добавить задачу в роль, то рабочий каталог будет выглядеть следующим образом:

/path/to/project/roles/role_name/tasks

Кроме того, плагины file и pipe запускаются из папки role/files , если она существует:

/path/to/project/roles/role_name/files - это означает, что ваша команда ls -1 *.txt

предостережение:

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

Я действительно удивляюсь, что в прецеденте для файла, который находится внутри проектов, есть папки, но имя неизвестно заранее. Откуда появился такой файл? Нельзя ли добавить слой между созданием файла и его использованием в Ansible... или с фиксированным локальным путем в качестве переменной? Просто любопытно;)

Ответ 2

Просто хотел добавить дополнительный ответ... У меня такая же проблема, как и вы, где я создаю несложный пакет на лету и копирую артефакты (rpms) в папку с файлами ролей, а мои rpms имеют версии в имя файла.

Когда я запускаю незанятую игру, я хочу, чтобы она установила все rpms, независимо от имени файла.

Я решил это, используя механизм with_fileglob в недоступном:

- name: Copy RPMs
  copy: src="{{ item }}" dest="{{ rpm_cache }}"
  with_fileglob: "*.rpm"
  register: rpm_files

- name: Install RPMs
  yum: name={{ item }} state=present
  with_items: "{{ rpm_files.results | map(attribute='dest') | list }}"

Я нахожу его немного более чистым, чем механизм поиска.