【ansible】僕がansibleを書くときに気をつけている事


昔のバージョンに比べて大分便利(自分の書き方が古く)になってきたので、自分のdotfileの管理をansibleに切り替えて色々触ってみた時のメモ


## 環境

* Mac OSX Yosemite(10.10.5)
	 * python 2.7.10
		* ansible 1.9.4

## 参考にしたサイト

* [Ansible-docs Best Practices](http://docs.ansible.com/ansible/playbooks_best_practices.html)
* [Ansible-docs All Modules](http://docs.ansible.com/ansible/list_of_all_modules.html)
* [Ansible コーディング規約 (の例)](http://tdoc.info/blog/2014/10/09/ansible_coding.html)



## Best Practicesのディレクトリレイアウトは目を通す

色んなリポジトリを見ていると結構色んなディレクトリ構成でansibleを書いているような気もしますが、公式ドキュメントの[ディレクトリレイアウト](http://docs.ansible.com/ansible/playbooks_best_practices.html#directory-layout)に記載されてあるのでそれを参考にしたディレクトリ構成で書こう(あるいは目指す)


## 判定に関する事(when系)

モジュールだけでは解決できない問題が色々とある。


### playbook実行結果のchangedは常に対象ホストの振舞いが変わった時だけchangedにする

* [【ansible】強制的にchangedを発生させない方法](http://qiita.com/ryurock/items/639e5f7e49d25c3b6d75)

で記載したが


> 自分が書いたplaybookであれば、これは気にしなくてよいchangedだ。などansibleの実行結果を見てすぐ判断できるだろうが、このplaybookを他人が実行した時に changed がでた場合に「おや、何か設定が何か変わったのか？」と思ってしまう。
changedは対象のOSの振る舞いが変わった時だけchangedになる方が望ましいと思う。

そうしないとchangedが怖くなり、段々production,staging,develop等で共通のtaskが書けなくなり、各環境に応じたtasksが出来上がっていく過程に入る。その時点で結構「秘伝のタレ」は進んでいるはず。
何のための冪等性だがわかんなくなるよね・・・って感じる。

## whenは早いのでなるべく実行条件分岐はなるべくwhenで書く

体感速度的な話なのですが、[changed_when](http://docs.ansible.com/ansible/playbooks_error_handling.html#overriding-the-changed-result)より[when](http://docs.ansible.com/ansible/playbooks_error_handling.html#controlling-what-defines-failure)のほうがplaybook実行の体感速度的に早いと感じることが多々あるのでwhenを使おう
(おそらくchaged_whenはactionを実行してからwhen判定を行っているように感じる。間違っていたらごめんなさい)


### OS固有のmoduleの場合には ``` when: "ansible_os_family == '{uname}'" ``` をつける

例えばnkfのインストールするタスクを書く際にターゲットOSをOSXに限定した場合ならこう書くと思う

```roles/nkf/install/tasks/main.yml
- name: Install the nkf from homebrew
  homebrew: name=nkf state=present
```

でもnkfってゲストOSでも必要だよね？ってなったときに無駄なrolesを作ってしまわないようにこう書けば一つのroleで違うOSに同じ動作を保証することができる

```roles/nkf/install/tasks/main.yml
- name: Install the nkf from homebrew
  homebrew: name=nkf state=present
  when: "ansible_os_family == 'Darwin'"

- name: Install the nkf from yum
  yum: pkg=nkf state=present
  when: "ansible_os_family == 'RedHat'"
```

### ignore_errosよりも``` failed_when: no ```で

エラーになっても無視していいよってので[ignore_errors](http://docs.ansible.com/ansible/playbooks_error_handling.html#ignoring-failed-commands)あるが、これなんか

「キモい・・・・」

というか、playbook実行時にignore_errorsが発生すると表示上はfailedが表示される。


コンソールで赤色の何かが出るのは、ansibleじゃなくても何か後ろめたさがある。

ignore_errorsでやりたいことはfailを無視することだから、無視するならfailを発生させないように

```
failed_when: no
```

と書こう。
そうすればコンソールでfailedは出てこない。


## 依存ロールが出てきてしまったならmetaを使う

例えばCUIでchromeを操作する[chrome-cli](https://github.com/prasmussen/chrome-cli)をインストールする場合にchromeが必要になる。

その場合のtaskの書き方はこうしている

### chrome-cliをインストールするタスク

```roles/homebrew/brew/chrome-cli/tasks/main.yml
- name: Install the chrome-cli in the brew.
  homebrew: name=chrome-cli state=present
  when: "ansible_os_family == 'Darwin'"
```

chrome-cliをhomebrewでインストールするだけのタスク

### google-chromeをインストールするタスク


```roles/homebrew/brew-cask/google-chrome/tasks/main.yml
- name: Install the google-chrome in the brew-cask
  homebrew_cask: name=google-chrome state=present
  when: "ansible_os_family == 'Darwin'"
```

google-chromeをhomebrew-caskでインストールするだけのタスク

### chrome-cliがhomebrew/brew-cask/google-chromeの依存関係のmeta

```homebrew/brew/chrome-cli/meta/main.yml
dependencies:
  - { role: homebrew/brew-cask/google-chrome }
```


```
chrome-cli
├── meta
│   └── main.yml
└── tasks
    └── main.yml

google-chrome
└── tasks
    └── main.yml
```

２つのロールを書いてmetaで依存関係を記載する

## wgetしたいと思った時はget_urlで

* [get_url](http://docs.ansible.com/ansible/get_url_module.html)


表題の通り。自分メモ用


## ファイル・ディレクトリの操作

これもよく忘れてansibleモジュールのドキュメントをよく見るので自分用メモ

### ファイル・ディレクトリの存在チェックはstat

* [module stat](http://docs.ansible.com/ansible/stat_module.html)

上記の[examples](http://docs.ansible.com/ansible/stat_module.html#examples)見ればだいたいのことはできる


## 最後に

追記があったら追加していきます。