Вопрос или проблема
Я пытаюсь прочитать пароль базы данных на удаленном хосте из файла /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 }}"
Объяснение кода:
- В первом задании мы используем
slurp
для чтения файла, и результат сохраняется в переменнойpasswordfile
. - Второе задание использует модуль
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.