Как считать строку из файла в формате INI в переменную Ansible?

Вопрос или проблема

Я пытаюсь прочитать пароль базы данных на удаленном хосте из файла /etc/mysql/debian.cnf. Формат файла приведен ниже.

# Автоматически сгенерировано для скриптов Debian. НЕ ТРОГАЙТЕ!
[client]
host     = localhost
user     = root
password = 5unnyv4l3
socket   = /var/run/mysqld/mysqld.sock
[mysql_upgrade]
host     = localhost
user     = root
password = 5unnyv4l3
socket   = /var/run/mysqld/mysqld.sock
basedir  = /usr

Есть ли способ извлечь поле password, чтобы я мог удалить пользователя mysql через Ansible?

Судя по всему, модуль slurp будет работать для ваших требований:

- name: извлечь пароль из файла
  slurp:
    src: /etc/mysql/debian.cnf
  register: mypasswordfile

- name: Установить пароль пользователя
  user: name=newUser
    password="{{ passwordfile['content'] | b64decode | regex_findall('password = \"(.+)\"') | first }}"

Отредактировано после тестирования и исправления.

Если файл локален для системы ansible, вы можете использовать ini с помощью lookup, который будет считывать значения из файла в формате ini. Если ваш файл удаленный, вы можете использовать fetch/slurp, чтобы получить его копию на локальную систему.

Я предположу, что выполнение поиска будет чем-то вроде

- debug: msg="Пароль - {{ lookup('ini', 'password section=client file=my.cnf') }}"

Вы можете использовать команду или модуль shell и сделать это с помощью awk/sed, что-то вроде:

- name: получить значение в блоке из файла
  command: >
         awk -F ' *= *' '{ if ($1 ~ /^\[/) section=$1;
         else if ($1 ~ /^password/ && section ~ /^\[client\]$/ ) print $2 }'
         "{{ file_path }}"
  register: password_value

В этом случае, чтобы обработать комментарий в той же строке, вы можете сделать

- name: установка пароля без комментариев
  set_fact:
    password: "{{ password_value.stdout.split('#')[0] }}"

Другой подход, используя slurp плюс фильтр community.general.from_ini:

- name: Slurp файл ini
  slurp:
    src: /etc/myfile.ini
  register: myfile
- name: Поместить содержимое ini в словарь в переменную
  set_fact:
    ini_data: "{{ myfile.content | b64decode | community.general.from_ini }}"
- name: Печать или чтение содержимого ini
  debug:
    msg: "{{ ini_data }}"

Документация:

Ответ или решение

Для того чтобы извлечь значение поля password из файла INI-формата, расположенного на удаленном хосте, вы можете использовать несколько подходов в рамках Ansible. В данном случае, рассмотрим несколько методов и уточним каждый из них с точки зрения эффективности и читаемости кода.

Использование модуля slurp

Первый подход — это использование модуля slurp. Этот модуль считывает содержимое файла на удалённой системе и кодирует его в base64. Полученное значение можно декодировать и обработать дальше.

- name: Извлечение пароля из файла
  slurp:
    src: /etc/mysql/debian.cnf
  register: passwordfile

- name: Установка пароля пользователя
  user: 
    name: newUser
    password: "{{ passwordfile['content'] | b64decode | regex_findall('password *= *\"?(.*?)\"?') | first }}"

Объяснение кода:

  1. В первом задании мы используем slurp для чтения файла, и результат сохраняется в переменной passwordfile.
  2. Второе задание использует модуль user, чтобы создать пользователя с указанием пароля. Мы извлекаем значение пароля, используя b64decode для декодирования содержимого и regex_findall для поиска строки, содержащей пароль.

Использование lookup-плагина ini

Если файл находится локально (или если вы можете его скопировать), можно использовать lookup-плагин ini. Однако в вашем случае файл находится на удаленном сервере.

- debug: msg="Пароль: {{ lookup('ini', 'password section=client file=/etc/mysql/debian.cnf') }}"

Использование командного модуля с awk

Другой способ — это использование командного модуля, который позволяет извлекать необходимое значение с помощью утилит как awk или sed.

- name: Получение значения из файла
  command: >
    awk -F ' *= *' '{ if ($1 ~ /^\[/) section=$1;
    else if ($1 ~ /^password/ && section ~ /^\[client\]$/ ) print $2 }'
    /etc/mysql/debian.cnf
  register: password_value

- name: Установка пароля без комментариев
  set_fact:
    password: "{{ password_value.stdout.split('#')[0] }}"

Использование community.general.from_ini

Недавно появившийся вариант — использование фильтра from_ini из коллекции community.general. Это позволит вам удобно преобразовать содержимое INI-файла в словарь.

- name: Slurp ini file
  slurp:
    src: /etc/mysql/debian.cnf
  register: myfile

- name: Конвертация в словарь
  set_fact:
    ini_data: "{{ myfile.content | b64decode | community.general.from_ini }}"

- name: Печать содержимого INI
  debug:
    msg: "{{ ini_data }}"

Итог

Каждый из перечисленных подходов имеет свои достоинства. Выбор метода зависит от вашего сценария использования и нужд. Модуль slurp с использованием регулярных выражений позволяет извлекать данные из удаленных файлов эффективно, в то время как from_ini облегчает работу с форматированными данными. Если вам нужна простота и лаконичность, используйте фильтры; если вы работаете с большими объемами данных или сложными файлами, возможно, лучше всего подойдет awk.

Все описанные методы позволяют не только извлечь пароль из INI-файла, но и сделать это в соответствии с хорошими практиками написания кода, сохраняя читаемость и понятность вашего playbook.

Оцените материал
Добавить комментарий

Капча загружается...