Search code examples
mysqlubuntuvagrantansible

Install MySQL with ansible on ubuntu


I have a problem installing MySQL with ansible on a vagrant ubuntu,

This is my MySQL part

---
- name: Install MySQL
  apt:
    name: "{{ item }}"
  with_items:
    - python-mysqldb
    - mysql-server

- name: copy .my.cnf file with root password credentials
  template: 
    src: templates/root/.my.cnf
    dest: ~/.my.cnf
    owner: root
    mode: 0600

- name: Start the MySQL service
  service: 
    name: mysql 
    state: started
    enabled: true

  # 'localhost' needs to be the last item for idempotency, see
  # http://ansible.cc/docs/modules.html#mysql-user
- name: update mysql root password for all root accounts
  mysql_user: 
    name: root 
    host: "{{ item }}" 
    password: "{{ mysql_root_password }}" 
    priv: "*.*:ALL,GRANT"
  with_items:
    - "{{ ansible_hostname }}"
    - 127.0.0.1
    - ::1
    - localhost 

And I have this error

failed: [default] => (item=vagrant-ubuntu-trusty-64) => {"failed": true, "item": "vagrant-ubuntu-trusty-64"}
msg: unable to connect to database, check login_user and login_password are correct or ~/.my.cnf has the credentials
failed: [default] => (item=127.0.0.1) => {"failed": true, "item": "127.0.0.1"}
msg: unable to connect to database, check login_user and login_password are correct or ~/.my.cnf has the credentials
failed: [default] => (item=::1) => {"failed": true, "item": "::1"}
msg: unable to connect to database, check login_user and login_password are correct or ~/.my.cnf has the credentials
failed: [default] => (item=localhost) => {"failed": true, "item": "localhost"}
msg: unable to connect to database, check login_user and login_password are correct or ~/.my.cnf has the credentials

my .my.cnf is

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

and when copied on the server

[client]
user=root
password=root

I don't understand why, ~/.my.cnf is created

Project Github

Thanks


Solution

  • When mysql-server is installed headlessly, there's no password. Therefore to make .my.cnf work, it should have a blank password line. Here's what I tested with for a .my.cnf:

    [client]
    user=root
    password=
    

    It's also slightly strange to put .my.cnf in your vagrant user directory as owned by root and only readable as root.

    After ensuring the password was blank in .my.cnf, I was able to properly set the password for root in those four contexts. Note that it fails to run after that, since .my.cnf would need to be updated, so it fails the idempotency test.

    There's a note on the ansible mysql_user module page that suggests writing the password and then writing the .my.cnf file. If you do that, you need a where clause to the mysql_user action (probably with a file stat before that).

    Even more elegant is to use check_implicit_admin along with login_user and login_password. That's beautifully idempotent.

    As a third way, perhaps check_implicit_admin makes it even easier.

    Here's my successful playbook showing the above, tested with a few fresh servers. Kinda proud of this. Note .my.cnf is unnecessary for all of this.

    ---
    - hosts: mysql
      vars:
        mysql_root_password: fart
      tasks:
      - name: Install MySQL
        apt: name={{ item }} update_cache=yes cache_valid_time=3600 state=present
        sudo: yes
        with_items:
        - python-mysqldb
        - mysql-server
      #- name: copy cnf
      #  copy: src=.my.cnf dest=~/.my.cnf owner=ubuntu mode=0644
      #  sudo: yes
      - name: Start the MySQL service
        sudo: yes
        service: 
          name: mysql 
          state: started
          enabled: true
      - name: update mysql root password for all root accounts
        sudo: yes
        mysql_user: 
          name: root 
          host: "{{ item }}" 
          password: "{{ mysql_root_password }}"
          login_user: root
          login_password: "{{ mysql_root_password }}"
          check_implicit_admin: yes
          priv: "*.*:ALL,GRANT"
        with_items:
          - "{{ ansible_hostname }}"
          - 127.0.0.1
          - ::1
          - localhost 
    

    (edit- removed my.cnf)