【Ansible】Mysql5.7でrootユーザのパスワードを再設定etc...

## 概要
- Mysql5.7でrootユーザのパスワードを変更したり、db作成したり、user作成したり、兎に角苦労したので、メモを残す

## Ansibleで行うこと
1. mysql5.7のインストール
2. 各種モジュールのインストール
3. .my.cnfの配置
4. デフォルトのrootのパスワードの取得
5. rootユーザのパスワード再設定
6. .my.cnfの削除

## 環境
- 実行対象サーバ
    - MySQL 5.7.19
    - Centos7.1.1503
- ansibleサーバ
    - ansible2.3.1.0
    - CentOS7.1.1503

## ディレクトリ構成

```
.
├── main.yml
├── group_vars
│   └── vaults.yml
├── hosts
└── roles
    └── mysql
        ├── tasks
        │   ├── main.yml
        │   ├── mysql-module.yml
        │   └── settings.yml
        ├── templates
        │   └── my.cnf
        └── vars
           └── main.yml   
```
- main.yml: playbook
- vaults.yml: 暗号化したファイル(パスワード等を管理)
- hosts: Inventoryファイル
- roles/mysql/tasks/main.yml: mysqlロールのメインタスク
- mysql-module.yml: モジュールインストールのタスク
- <font color="red">settings.yml: **初期設定** <-今回取り上げたところ</font>
- my.cnf: サーバに配置するファイル
- roles/mysql/vars/main.yml: 変数管理

---
1 ~ 2はサクッと紹介しちゃいます

### 1. mysql5.7のインストール

```yml:roles/mysql/tasks/main.yml
---
- name: yum install mysql5.7
  yum: name=http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
```

### 2. 各種モジュールのインストール

```yml:roles/mysql/tasks/mysql-module.yml
---
- name: yum install mysql-modules
  yum: name={{ item }}
  with_items: "{{ install_lists }}"
```

ここの<font color="red">install_lists</font>は`roles/mysql/vars/main.yml`で管理している<font color="red">install_lists</font>の要素を順番にループして**item**という変数から取り出して、yum installさせています。

```yml:roles/mysql/vars/main.yml
---
install_lists:
  - mysql
  - mysql-devel
  - mysql-server
  - mysql-utilities
  - MySQL-python
```

<font color="red">※MySQL-pythonはansibleでリモートで操作する際に必要になるものです。</font>


このモジュールについては[こちら](https://qiita.com/Tocyuki/items/3efdf4cfcfd9bea056d9)を参考にすると良いと思います。

### 3. .my.cnfの配置
- templateモジュールを使って`roles/mysql/templates/my.cnf`を対象のサーバの`/root/`配下に`.my.cnf`というファイル名で配置する。
- 各パラメータに必要な値を設定する。
    1. src: 配置する、ファイルのパス
    2. dest: 配置先のパス
    3. owner: ファイルのオーナー権限
    4. group: ファイルのグループ権限

```yml:roles/mysql/tasks/settings.yml
- name: deploy .my.cnf
  template:
    src: templates/my.cnf
    dest: /root/.my.cnf
    owner: root
    group: root
```
- `roles/mysql/templates/my.cnf`は下記のようになっています。

```yml:roles/mysql/templates/my.cnf
[client]
user = {{ mysql.root_user.root.username }}
password = {{ mysql.root_user.root.password }}
```
<font color="red">※`{{ mysql.root_user.root.username }}`と`{{ mysql.root_user.root.password }}`は`group_vars/vaults.yml`という暗号化されたファイルで管理されている変数です。</font>

##### もしベタでいいからとりあえず動きを確認したい場合は下記のように設定して下さい。

```yml:roles/mysql/templates/my.cnf
[client]
user = root
password = {rootに再設定するパスワード}
```

### 4. デフォルトのrootのパスワードの取得
<font color="red">※必ず、`get temporary password`タスクよりも前にmysqlの起動のタスクを設定することを忘れずに</font>

- serviceモジュールを使用して各パラメータに必要な値を設定する。
    1. name: 起動するサービス名
    2. state: アクション名
    3. enabled: 自動起動(yes/no)

```
- name: start mysql
  service: name=mysqld state=started enabled=yes
```

- mysql5.7では初期パスワードが`/var/log/mysqld.log`に<font color="red">temporary password</font>として吐き出されているので、**cat**,**grep**,**awk**コマンドを駆使して、パスワード部分だけを取り出します。

```
- name: get temporary password
  shell: cat /var/log/mysqld.log | grep "temporary password" | awk '{print $11}'
  register: mysql_default_password
```

awkコマンドについては[こちら](http://www.atmarkit.co.jp/ait/articles/1706/02/news017.html)をご覧んください。

ひとまず、これで`mysql_default_password`に下記のように格納されます。

```
{
        "changed": true,
        "cmd": "cat /var/log/mysqld.log | grep \"temporary password\" | awk '{print $11}'",
        "delta": "0:00:00.005036",
        "end": "2017-09-27 12:51:31.361478",
        "rc": 0,
        "start": "2017-09-27 12:51:31.356442",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "k0E?76tKswhd",
        "stdout_lines": [
            "k0E?76tKswhd"
        ]
}
```

### 5. rootユーザのパスワードを再設定

- rootユーザのパスワードの再設定は、shellモジュールを使用して、コマンドを実行させます。

```yml:roles/mysql/tasks/settings.yml
- name: change root user password
  shell: |
    mysql -u root -p'{{ mysql_default_password.stdout }}' --connect-expired-password -e "set password for root@'localhost'=password('{{ mysql.root_user.root.password }}');"

```

`{{ mysql_default_password.stdout }}`は先ほど`get temporary password`タスクで**mysql_default_password**に格納されたmysqlのデフォルトのパスワードを取り出しています。

<font color="red">※`{{ mysql.root_user.root.password }}`は`group_vars/vault.yml`で暗号化されている変数の値を取り出しています。</font>

### 6. .my.cnfの削除

- <font color="orange">これは人それぞれですが、個人的にパスワードをそのままサーバに残しておくのが嫌なのでこのタスクを設けています。</font>

- fileモジュールを使用して、各パラメータに必要な値を設定する。
    1. name: 削除するファイルのパス

```yml:roles/mysql/tasks/settings.yml
- name: delete /root/.my.cnf
  file: name=/root/.my.cnf  state=absent
```

### 以上

---

# おまけ
- おまけにデータベースの作成と新規ユーザの作成を行ったのでそちらも記載しておきます。

### データベースの作成

- mysqldbモジュールを使用して各パラメータに必要な値を設定する。
    1. name: 作成したいデータベース名

```yml:roles/mysql/tasks/settings.yml
- name: create mysql database
  mysql_db: name={{ mysql.database }} state=present
```

<font color="red">※`{{ mysql.database }}`は`group_vars/vault.yml`で暗号化されている変数の値を取り出しています。</font>

### ユーザの追加(権限付与) 

- mysql_userモジュールを使用して各パラメータに必要な値を設定する。
    1. name: ユーザ名
    2. host: 接続するホスト名
    3. password: パスワード
    4. priv: ユーザに与えるdbの権限

```yml:roles/mysql/tasks/settings.yml
- name: create mysql user
  mysql_user: name={{ item.value.username }} host=localhost password={{ item.value.password }} priv={{ item.value.database_name }}.*:ALL,GRANT state=present
  with_dict: "{{ mysql.new_user }}"
```
<font color="red">※`{{ mysql.new_user }}`は暗号化されている変数の値を取り出している。</font>


# おわり
(もうちょっとディレクトリ構成とか、スマートにタスクを書きたい...)