Buzut
Buzut

Reputation: 5153

Ansible and nested variables in loops

I there a way in Ansible to access variables in variables in a loop? For instance, configuring debconf to install a MySQL/MariaDB server needs two instructions like so:

- name: Define maria root password
  shell: echo mysql-server mysql-server/root_password password {{ mysqlRootPass }} | debconf-set-selections

- name: Define maria root password again
  shell: echo mysql-server mysql-server/root_password_again password {{ mysqlRootPass }} | debconf-set-selections

But that would be way more compact if I could do that:

- name: Define maria root password
  shell: {{ item }}
  with_items:
    - "{ echo mysql-server mysql-server/root_password password {{ mysqlRootPass }} | debconf-set-selections }"
    - "{ echo mysql-server mysql-server/root_password_again password {{ mysqlRootPass }} | debconf-set-selections }"

Obviously, that doesn't work.

so is there a way to make it work? Is there a better way of doing it? Am I missing something?

Upvotes: 2

Views: 3079

Answers (2)

Wtower
Wtower

Reputation: 19902

The {{ }} notation in Ansible comes from Jinja2 templates, it essentially directs Ansible to replace this with the contents of that variable.

with_items introduces the special variable item, which is the particular item of the current loop.

Therefore, you instruct the command module to execute { echo..., namely whatever it is you have in with_items. You only need the command itself: echo....

Reference: Ansible docs: using variables and Jinja2

Upvotes: 1

Arbab Nazar
Arbab Nazar

Reputation: 23771

Here is my complete working MySQL role, that might help you.

vars/main.yml

mysql_root_pass: mypassword #MySQL Root Password

tasks/main.yml

---
 - name: Install the MySQL packages
   apt:
     name: "{{ item }}"
     state: installed
     update_cache: yes
   with_items:
     - mysql-server-5.6
     - mysql-client-5.6
     - python-mysqldb
     - libmysqlclient-dev

 - name: Update MySQL root password for all root accounts
   mysql_user:
     name: root
     host: "{{ item }}"
     password: "{{ mysql_root_pass }}"
     state: present
   with_items:
     - "{{ ansible_hostname }}"
     - 127.0.0.1
     - ::1
     - localhost

 - name: Copy the root credentials as .my.cnf file
   template:
     src: root.cnf.j2
     dest: "~/.my.cnf"
     mode: 0600

 - name: Ensure Anonymous user(s) are not in the database
   mysql_user:
     name=''
     host: "{{ item }}"
     state: absent
   with_items:
     - localhost
     - "{{ ansible_hostname }}"

 - name: Remove the test database
   mysql_db:
     name: "test"
     state: absent
   notify:
     - Restart MySQL

templates/root.cnf.j2

[client]
user=root
password={{ mysql_root_pass }}

handlers/main.yml

---
 - name: Restart MySQL
   service:
     name: mysql
     state: restarted

My site.yml look like this:

---
- hosts: all
  become: yes
  gather_facts: yes
  roles:
    - mysql

If you are just looking to update the password of already configured MySQL:

In vars/main.yml

mysql_old_root_pass: olmysqldpassword
mysql_root_pass: newmysqlpassword 

In tasks/main.yml

- name: Set root user password
  mysql_user:
    name: root
    host: "{{ item }}"
    password: "{{ mysql_root_pass }}"
    check_implicit_admin=yes
    login_user: root
    login_password: "{{ mysql_old_root_password }}"
    state: present
  with_items:
    - "{{ ansible_hostname }}"
    - 127.0.0.1
    - ::1
    - localhost

Hope this will help you. If you need any help, please check this github link.

Upvotes: 1

Related Questions