Check! Vagrant の ansible_local で、ansible が見つからないと失敗してしまう場合の原因と対処

こんにちは、オークファンの @dz_ こと大平かづみです。

Prologue - はじめに
====
最近、ローカルに環境を作るために使いだした [Vagrant](https://www.vagrantup.com/ "Vagrant by HashiCorp") 、少しずつカスタマイズを進めています。

シェルでのプロビジョンが面倒になったので [Ansible](https://www.ansible.com/ "Ansible is Simple IT Automation") を使いたいが、ホストOSが Windows だと Cygwin に頼ることになり、これまた面倒です。そこで、Provisioner に `ansible_local` を使うことにしました。

が、しかし！！

後述のエラーで数日翻弄した末に、やっと解決しましたので共有いたしますね(*ﾉД`)ﾉ

※ なお、今回はホストOSが Windowsですが、ホストOSの種類は関係ありません。Mac OS でも同様エラーを確認済みです。

結論: 原因は Ansible のバージョンが合わないため
====
結論から申しますと、 `ansible_local` Provisioner は、Ansible の現行バージョン `2.0.1` では動きません。（2016年3月時点）

そのため、先に Ansible の 1.x 系バージョンをインストールさせることで、プロビジョニングで Ansible の Playbook を実行できるようになります。

それでは、以下、詳細を記載していきます。

詳細
====
Ansible Local Provisioner とは
----

Vagrant では、プロビジョニングに Ansible を使うことができます。2つの Provisioner が用意されており、`ansible` と `ansible_local` です。

| Provisioner | プロビジョニングの仕組み |
|-------------|---|
| `ansible` | ホストOS上の Ansible を使ってプロビジョニング |
| `ansible_local` | **ゲストOS上の Ansible** を使ってプロビジョニング |

`ansible_local` なら、ホストOSに Ansible を入れなくていいのでローカル環境を汚さずに済みます。

- [Ansible Local - Provisioning - Vagrant by HashiCorp](https://www.vagrantup.com/docs/provisioning/ansible_local.html "Ansible Local - Provisioning - Vagrant by HashiCorp")

Ansible が見つからないエラー
----
しかし、いざ `ansible_local` を使ってみると以下のエラーに遭遇しました。

```bash
# Vagrant を起動したところ...
vagrant up

...<略>...

==> default: Running provisioner: ansible_local...
    default: Installing Ansible...
The Ansible software could not be found! Please verify
that Ansible is correctly installed on your guest system.

If you haven't installed Ansible yet, please install Ansible
on your Vagrant basebox, or enable the automated setup with the
`install` option of this provisioner. Please check
https://docs.vagrantup.com/v2/provisioning/ansible_local.html
for more information.

```

`The Ansible software coud not be found!` と、Ansible をみつけられないようです。

エラーメッセージでも示唆されてるように、 `ansible_local` では、 `ansible.install = true` を指定することでゲストOSに Ansible を自動でインストールしてくれます。（下記スクリプト参照）

しかし、自動インストールを指定しても、このエラーでこけてしまうのです。

```ruby:Vagrantfile
Vagrant.configure(2) do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.provision "ansible_local" do |ansible|
    ansible.playbook = "playbook.yml"
    ansible.install = true    # Ansible を自動でインストールさせる指定
  end
end
```

ヒント
----
上記エラーにはなりますが、実は Ansible はちゃんとインストールされていました。

```bash:vagrantゲストOSにて
vagrant@vagrant-ubuntu-trusty-64:~$ ansible --version
ansible 2.0.1.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```

お手上げでしたので、ベテランの先輩に相談したところ、Ansible のバージョンを疑ってみたは？とのこと！

対処
----
そこで、以下のように Ansible の 1.x 系バージョンを明示的にインストールしたところ、無事に動きましたとさ！

なお、ゲストOSは [Ubuntu](http://www.ubuntu.com/ "The leading OS for PC, tablet, phone and cloud | Ubuntu") を想定しています。ほかのOSをご利用の場合は、 [Ansible のインストール方法](http://docs.ansible.com/ansible/intro_installation.html "Installation — Ansible Documentation")をご確認くださいませ。

```ruby:Vagrantfile
Vagrant.configure(2) do |config|
  config.vm.box = "ubuntu/trusty64"

  # 先に Ansible 1.x をインストールさせる
  config.vm.provision :shell, path: "install-ansible.sh"

  # Ansible_local で任意の Playbook を実行する
  config.vm.provision "ansible_local" do |ansible|
    ansible.playbook = "playbook.yml"
  end
end
```

```bash:install-ansible.sh
#!/usr/bin/env bash

# PPA から Ansible 1.x 系バージョンのリポジトリを登録する
apt-get install -y software-properties-common
apt-add-repository -y ppa:ansible/ansible-1.9
apt-get update

# Ansible 1.x 系バージョンをインストールする
apt-get install -y ansible=1.9.4-1ppa~trusty
```

できましたー (*´･ω･)ﾉｼ

Epilogue - おわりに
====
今回は、悩みに悩んだ末に、先輩のデプロイ王子こと @kazumihirose さんに相談したところ、Ansible のバージョンが原因ではないかと勘所を教えてもらい、解決しました！頼りになります、いつもありがとうございます！

追記: ホストOSが Windows の場合、Ansible Local のプロビジョニングに失敗します
====
上記の対処で、起動時の Ansible Local によるプロビジョニングは正常に動くようになったのですが、起動後にプロビジョニングしようとすると以下のエラーが出る場合は、別要因です。
> ansible local provisioner:
 > * `playbook` does not exist on the guest: C:/vagrant/ansible/playbook.yml

以下にパッチを提供されている方いらっしゃるようです。ご自身の判断でご利用くださいませ。（私は試してません。）
[Use patched ansible provisioner for Windows host · BitKids/BitKidsServer@0c68bd7](https://github.com/BitKids/BitKidsServer/commit/0c68bd76327b6725779bf0f899a04d156ae202f6 "Use patched ansible provisioner for Windows host · BitKids/BitKidsServer@0c68bd7")