The /etc/mysql/debian.cnf
file follows standard INI format with sections ([client]
, [mysql_upgrade]
) and key-value pairs. We need to extract the password
value from the [client]
section programmatically.
Ansible provides several approaches to handle INI files:
Option 1: Using the ini_file Lookup Plugin
- name: Read MySQL password from INI file
ansible.builtin.set_fact:
mysql_password: "{{ lookup('ini', 'password section=client file=/etc/mysql/debian.cnf') }}"
Option 2: Using the community.general.ini Module
- name: Parse INI file with dedicated module
community.general.ini:
path: /etc/mysql/debian.cnf
section: client
option: password
dest: mysql_password
Here's a full implementation for creating a MySQL user with the extracted password:
- hosts: database_servers
vars:
new_mysql_user: app_user
new_mysql_password: "{{ lookup('ini', 'password section=client file=/etc/mysql/debian.cnf') }}"
tasks:
- name: Ensure MySQL user exists
community.mysql.mysql_user:
name: "{{ new_mysql_user }}"
password: "{{ new_mysql_password }}"
priv: "*.*:ALL"
state: present
login_user: root
login_password: "{{ new_mysql_password }}"
When working with sensitive passwords:
- Always use
no_log: true
for tasks handling credentials - Consider using Ansible Vault for storing sensitive values
- Set appropriate file permissions on the INI file (600 recommended)
For more complex scenarios:
- name: Safe extraction with default value
set_fact:
mysql_password: "{{ lookup('ini', 'password section=client file=/etc/mysql/debian.cnf') | default('fallback_password') }}"
When automating MySQL administration tasks with Ansible, we often need to retrieve credentials from configuration files. The /etc/mysql/debian.cnf
file presents a common challenge with its INI-style format containing multiple sections.
Ansible provides the ini
lookup plugin that can handle basic INI file parsing. Here's how to use it:
- name: Read MySQL password from debian.cnf
ansible.builtin.set_fact:
mysql_password: "{{ lookup('ini', 'password section=client file=/etc/mysql/debian.cnf') }}"
For files with multiple sections like debian.cnf, we need to specify which section contains our target value:
- name: Get password from specific section
ansible.builtin.set_fact:
db_creds: "{{ lookup('ini', 'password section=client file=/etc/mysql/debian.cnf type=properties') }}"
Here's a full playbook example that reads the password and uses it to create a MySQL user:
- hosts: database_servers
tasks:
- name: Extract MySQL root password
ansible.builtin.set_fact:
mysql_root_pass: "{{ lookup('ini', 'password section=client file=/etc/mysql/debian.cnf') }}"
- name: Create new database user
community.mysql.mysql_user:
name: "new_user"
password: "secure_password123"
priv: "*.*:ALL"
state: present
login_user: "root"
login_password: "{{ mysql_root_pass }}"
For more complex parsing needs, you might combine lineinfile
with regex:
- name: Extract password using regex
ansible.builtin.shell: |
grep -oP '^password\s*=\s*\K.*' /etc/mysql/debian.cnf | head -1
register: mysql_pass
changed_when: false
- name: Set password fact
ansible.builtin.set_fact:
extracted_pass: "{{ mysql_pass.stdout }}"
When working with sensitive credentials:
- Use
no_log: true
to prevent password exposure in logs - Consider using Ansible Vault for credential management
- Ensure minimal permissions on configuration files
Common issues and solutions:
# If encountering encoding issues:
- name: Read file with proper encoding
ansible.builtin.slurp:
src: /etc/mysql/debian.cnf
register: config_file
- name: Decode content
ansible.builtin.set_fact:
file_content: "{{ config_file.content | b64decode }}"