Ansible とServerspec 使っててなんでansible_spec  使わんの？

こんにちは。[@katsuhisa__](https://twitter.com/katsuhisa__) です。
本記事は、「[Ansible Advent Calendar 2017](https://qiita.com/advent-calendar/2017/ansible) 」の12/5(火)分です。

ぼくがだいすきな[ansible_spec ](https://github.com/volanja/ansible_spec)について紹介します。

## 本記事の対象読者

* Ansible つかっていて、これからServerspec 使おうと思っている方
* Ansible とServerspec をどちらも使用しているが、いろいろとつらみを感じている方

## ansible_spec とは？
**ansible_spec は、Ansible 用の設定ファイルとServerspec 用の設定ファイルを共通管理できるGem です。**
そう、Ansible とServerspec の色んなあれこれをばらばらに管理しなくてもよいのです。

## Ansible とServerspec をばらばらに管理ってどういうこと？
さて、ここでansible_spec 導入にまつわる論点の概要に改めて触れておきましょう。
Ansible とServerspec を素直に利用するだけだと、何が起こるのかをかんたんに流れで説明します。

ここでは、**MySQL の環境構築をするAnsible Playbook をつくり、Serverspec でテストを回す**、というシーンを想像してみます。

### 1. Ansible のPlaybook をつくる

超単純につくると以下のようになりますね。

```
Ansible_sample
├─hosts
├─site.yml
└─roles
    └─mysql
        ├─handlers
        │  └─main.yml
        ├─tasks
        │  └─main.yml
        └─templates
           └─my.cnf.j2

```

対象ホストをhosts で管理し、
MySQL の環境構築に関わる情報をroles/mysql 配下のディレクトリで管理します。

### 2. Serverspec でテストを書く

こちらも超単純につくると以下のようになりますね。

```
Serverspec_sample
├── Rakefile
└── spec
    ├── www.example.jp
    │   └── mysql_spec.rb
    └── spec_helper.rb
```

こちらは、対象ホストをspec 配下のサブディレクトリ名で管理し、
MySQL のテストコードをspec 配下のmysql_spec.rb で管理します。

### Ansible とServerspec を同じディレクトリで管理するとどうなる？
では、上述した2つを1つのディレクトリで管理してみましょう。

```
Ansible_Serverspec_sample
├─hosts
├─site.yml
├─roles
│   └─mysql
│       ├─handlers
│       │  └─main.yml
│       ├─tasks
│       │  └─main.yml
│       └─templates
│          └─my.cnf.j2
├── Rakefile
└── spec
    ├── www.example.jp
    │   └── mysql_spec.rb
    └── spec_helper.rb
```

なんだかやりたいことに対して、構成がやや複雑に感じられないでしょうか？

対象ホストは、

* Ansible ➔ hosts で管理
* Serverspec ➔ spec 配下のサブディレクトリ名で管理

と、それぞればらばらに管理しなければならないし、
MySQL に関するコードは、

* Ansible ➔ roles/mysql 配下で管理
* Serverspec ➔ spec 配下のmysqld_spec.rb で管理

しなければならず、MySQL に関するインフラコードを別々のディレクトリ配下で管理しなければなりません。

Ansible とServerspec は、それぞれ別のOSS なので当たり前っちゃー当たり前ですが管理が分断されています。

## ansible_spec をつかうとこうなる

というわけで、ansible_spec を使うと何が嬉しいのかを見てみましょう。
こうなります。

```
ansible_spec_sample
├── hosts                        
├── site.yml                     
├── roles
│   └── mysql
│       ├── handlers
│       │   └── main.yml
│       ├── spec                 
│       │   └── mysql_spec.rb
│       ├── tasks
│       │   └── main.yml
│       └── templates
│           └── my.cnf.j2
├── Rakefile                    
└── spec                        
    └── spec_helper.rb
```

※重複管理時と比較する説明のかんたんのために、ファイルを一部省略して記載しています。

ぱっと見ただけでもすっきりして気持ちが良いですね。たのしい。
ansible_spec を使えば、

* **Ansible のhosts をServerspec でも使いまわすことができ、対象ホストを重複管理しなくてもよい**

* **Ansible のroles 配下にServerspec のspec ファイルを置けるので、インフラコードを一元管理できる**

と、このようなメリットがあります。

**ばらばらに管理しなくてよい！さいこう！**となるわけです。

## ansible_spec を使わない派の人は何を考えているのか？
と、上述したように私はこの理由でansible_spec の利用を決定（というか見つけた瞬間に導入を即決）したのですが、世の中にはいろんな主義思想の方々がいます。

というわけで、さいごに利用しない派の人たちが、どういう風に考えているのかを見てみましょう。

### そもそもAnsible 使ってるんだったらServerspec いらないんじゃね？派

これは、Ansible の設計思想である「fail-fast」設計を尊重し、テストは行わないでも良い派の方たちの意見です。
また、Ansible で完成後のサーバーの状態を定義しているのに、なんでそれをさらに別のインフラコードで管理する必要があるの？ということですね。

ただ、テストコードがあると、開発プロセスに幅が持たせられて便利なんですよねえ・・・というのが私見です。

### 手動テスト派

基本的な思想は、「そもそもAnsible 使ってるんだったらServerspec いらないんじゃね？派」の方と同じで、**Ansible で完成後のサーバーの状態を定義しているのに、なんでそれをさらにテストコード書く必要があるの？**って人たちかな、と思っています。

ただ、いちおう確認しないと不安だから、いっそのこと手動でいいよね？と。
個人的な興味として、サーバー台数が増えた時にどう工夫しているのか聞いてみたいものです。手動テスト派の方がいれば教えてください。

### Ansible のassertモジュール使ってます派

これは私は使ったことがないのですが、どうなんでしょう。知っている方がいたら教えてください。書きにくい、という意見をよくみる気がしますが・・・

### 重複管理よりももっと大事なことがあるんだ派

ansible_spec の基本的な制約条件（といっても、限りなく少ないですが）を受け入れるにあたり、本来やりたかったテスト像と乖離が生じることを嫌う派の方たちです。詳細は割愛します。

ただ、これはだいたいの批判が、site.yml とPlaybook の書き方を変えれば解決するんじゃね？という話が多い気はしています。もし、「うっせえ若造が、そんなんじゃねえんだよ」という理由があればぜひ教えてください。

## まとめ
ansible_spec さいこうです。

だいすきなGem なので、ぜひ色んな人に使ってもらい、色んな人がOSS 貢献に取り組むことでansible_spec 自体が末永く続くと良いなあ、と思い記事を書いてみました。私も何か具体的な改善案やバグを見つけた際にはPR 出したいと思います。（➔たまたま今日見つけたのでPR 出しましたｗ➔先日マージしていただきました。）

どうもお読みいただきありがとうございました！
他の[Ansible Advent Calendar 2017](https://qiita.com/advent-calendar/2017/ansible) の記事も楽しみにしています。

[@katsuhisa__](https://twitter.com/katsuhisa__)