VagrantのShell ProvisionerでMySQLのテーブル作成を行う

# 背景
MySQLサーバーの仮想環境を開発チーム内で共有したいと思った場合、
ChefやAnsible、Puppetなどによるプロビジョニングが考えられます。
ですが、実際のところ、そこまで大がかりじゃなくてもいいという状況が割と多いのではないかと思ったので、
VagrantだけでMySQLサーバーのプロビジョニングを行う方法を考えました。

# 使用環境
- Windows10 Home
- GNU bash, version 4.4.12
- VirtualBox 5.1.22
- Vagrant 1.9.2

# 1, VirtualBoxとVagrantをインストール

VirtualBox
https://www.virtualbox.org/wiki/Downloads
Vagrant
https://www.vagrantup.com/downloads.html

環境変数のPathに自動で追加されるので、インストーラーに従うだけで大丈夫です。

```bash
$ vagrant --version
Vagrant 1.9.2
```

# 2, コマンドによる操作手順
以降、CygwinかMSYS等で実行すること。
自身はGit Bashを使用しました。
参考までにインストール先：https://git-scm.com/downloads
なお、ssh接続しない限り、コマンドプロンプトなどからでも実行できます。

また、今回使用するCentOS7のBox(bento/centos-7.3)はこちらから検索できます。
https://atlas.hashicorp.com/boxes/search

```bash
$ cd ~/Documents
$ mkdir -p MyVagrant/centos-mysql
$ cd MyVagrant/centos-mysql
$ vagrant plugin install vagrant-hostsupdater
$ vagrant init bento/centos-7.3 --minimal
# 下記の3ファイルを作成（全て「centos-mysql」の直下に作成）
# ファイルの中身に関しては、後述しています。
$ vi Vagrantfile
$ vi provisioner.sh
$ vi provisioner.sql
# 以降、管理者権限で実行する必要があります。（Windowsのhostsファイルに書き込みに行くため）
# hostnameを設定しなくてもよい場合は、管理者権限は不要です。
$ vagrant up
# MySQL serverが起動します。
# ==> default: mysql: [Warning] Using a password on the command line interface can be insecure.
#"最後にこちらのWarningログが出ますが、開発用なので支障ありません。

# ssh接続したい場合
$ vagrant ssh
# 終了する
$ vagrant halt
```

# 3, 各設定ファイルの内容
Vagrantfile, provisioner.sh, provisioner.sqlの3ファイルを使ってますが、
ヒアドキュメントを使用することでVagrantfile内にまとめて記述することも可能です。

## Vagrantfile
vagrant-hostsupdaterプラグインを使用して
"192.168.33.12"に"intra.nimzo.co.jp"でアクセスできるようにしています。

```ruby:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "geerlingguy/centos7"
  config.vm.hostname = "intra.nimzo.co.jp"
  config.vm.network "private_network", ip: "192.168.33.12"
 
  config.vm.provision "shell", :path => "provisioner.sh"
end
```

## provisioner.sh
Vagrantが実行するプロビジョニングのスクリプトです。
ちなみに、デフォルトではroot権限で実行されます。
明示的にVagrantfileで指定したい場合は
```:privileged => true``` をconfig.vm.provisionに付けておくことができます。

また、プロビジョニングに用いるスクリプトは冪等性を保証する必要があります。
こちらの実現方法に関しては下記の記事が参考になります。
[これだけ覚えておけばOK！シェルスクリプトで冪等性を担保するためのTips集](http://qiita.com/yn-misaki/items/3ec0605cba228a7d5c9a)
今回のシェルスクリプトでは、冒頭だけ簡単に実装しました。
簡単すぎて、冪等性とは言えないかもです。

```bash:provisioner.sh
#!/bin/sh

lookFile=/home/vagrant/provisioner.lock
if [ -e $lookFile ]; then
  exit
fi

touch $lookFile

# mariaDBとの競合を防ぐため
yum -y remove mariadb-libs
rm -rf /var/lib/mysql

# https://dev.mysql.com/downloads/repo/yum/を参照
yum -y localinstall http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
yum -y install mysql-community-server

# 必要最小限のMySQLの設定内容を書き込む
cat << __CONF__ >> /etc/my.cnf
character-set-server = utf8
default_password_lifetime = 0
__CONF__

# MySQLの自動起動を有効化し起動する
systemctl enable mysqld
systemctl start mysqld
# 初期パスワードを取得する
password=`cat /var/log/mysqld.log | grep "A temporary password" | tr ' ' '\n' | tail -n1`
 
mysql -u root -p${password} --connect-expired-password < /vagrant/provisioner.sql
```

## provisioner.sql
MySQLコマンドによるプロビジョニングです。

```sql:provisioner.sql
-- 初回のパスワードポリシーを満たすパスワードを設定（適当でよい）
SET password FOR root@localhost=password('uQvdquWj3=bW');

-- パスワードポリシーの変更
SET global validate_password_policy=LOW;
SET global validate_password_length=6;
-- パスワードの変更
SET password FOR root@localhost=password('vagrant');

-- ユーザーの作成
CREATE USER nimzo_user@localhost identified BY 'devnimzo';
-- データベースの作成
CREATE database nimzo;
-- テーブルの作成
CREATE TABLE IF NOT EXISTS `nimzo`.`users` (`user_id` INT NOT NULL COMMENT '',
  `is_deleted` TINYINT NOT NULL COMMENT '',
  `updated_at` TIMESTAMP COMMENT '',
  PRIMARY KEY (`user_id`) COMMENT '',
  UNIQUE INDEX `user_id_UNIQUE` (`user_id` ASC) COMMENT '')
ENGINE = InnoDB;

-- 権限の付与（IPアドレスによるアクセス元の制限は指定しない）
GRANT ALL ON *.* TO 'nimzo_user'@'localhost' IDENTIFIED BY 'devnimzo';
GRANT ALL ON *.* TO 'nimzo_user'@'%' IDENTIFIED BY 'devnimzo';
FLUSH PRIVILEGES;
```

# 構築したMySQLへの接続情報
以下、ホストマシンから接続する方法

- MySQLがローカルにインストールされている場合

```bash
$ mysql \
    --host=intra.nimzo.co.jp \
    --user=nimzo_user \
    --password=devnimzo \
    --database=nimzo
```

- MySQLがローカルにインストールされていない場合

こちらのClientツールが便利です。
https://sqlectron.github.io/
以下、「Sqlectron-1.20.2-win.zip」を使用した結果です。
![2017-05-13.png](https://qiita-image-store.s3.amazonaws.com/0/114728/5b39d726-b7bd-4aa3-d1d9-ff105bf2c8e0.png)

# 補足
statusコマンドを使うと、現在のvagrantの状態とそこからよく使われるコマンドが参照できる


```bash
$ vagrant status
Current machine states:
 
default running (virtualbox)
 
The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.
```

# 参考
[Vagrant公式ページ - Shell Provisioner](https://www.vagrantup.com/docs/provisioning/shell.html)
[Vagrantの/etc/hosts系プラグインを比べてみた](http://qiita.com/tag1216/items/0d10f67cb55651740df4)
[MySQL 5.7 を CentOS 7 に yum インストールする手順](http://weblabo.oscasierra.net/installing-mysql57-centos7-yum/)
[MySQLに外部ホストから接続できるように設定する](http://linuxserver.jp/%E3%82%B5%E3%83%BC%E3%83%90%E6%A7%8B%E7%AF%89/db/mysql/%E5%A4%96%E9%83%A8%E6%8E%A5%E7%B6%9A%E8%A8%B1%E5%8F%AF%E8%A8%AD%E5%AE%9A)