[俺の鞍] AnsibleでEmacsとZshを初期設定


VagrantでCentOSの空箱を作った後に、何はともあれ、EmacsとZshだけは準備しとこうというメモ。
「そこまで手動で設定したものをvagrant packageでエクスポートしとけば、いんじゃねえ！」というのもあるけど、Ansibleの簡単な使い方の勉強も兼ねて。

「俺の鞍(saddle)」というのは、[HappyHackingKeyboard(HHK)についての和田英一先生の談話](http://www.pfu.fujitsu.com/hhkeyboard/dr_wada.html)を思い出してのもの。

<上記サイトから引用>
> アメリカ西部のカウボーイたちは、馬が死ぬと馬はそこに残していくが、どんなに砂漠を歩こうとも、鞍は自分で担いで往く。馬は消耗品であり、鞍は自分の体に馴染んだインタフェースだからだ。
  いまやパソコンは消耗品であり、キーボードは大切な、生涯使えるインタフェースであることを忘れてはいけない。
［東京大学 和田英一 名誉教授の談話］

VMが変わっても、とりあえず、自分の体に馴染んだEmacsとZshは担いで往く！なんて。HHKは物理的なモノだから成立する例えなんでしょうけどね。。（一応HHKも鞍として使ってます。）

環境の前提は、母艦Macに、vagrantでCentOSの空箱(initして、upした程度の新品VM)がある状態。
そして、母艦Macには、既にansibleインストール済。

```
% ansible --version
ansible 1.9.0.1
```

空箱CentOSのアドレスは、192.168.17.11とする。

で、今回することは、母艦Macから、この空き箱にansibleで、次の6つのことをするだけ。

(1) TimezoneをAsia/Tokyoへ
(2) yumでzshをインストール
(3) 母艦の~/.zshrcをコピー 
(4) 標準のシェルをzshにする ------> めでたくzsh利用可！
(5) yumでemacsをインストール
(6) 母艦の~/.emacs.dをコピー ----> めでたくemacs利用可！

zshとemacsがあれば、あとは、直接なんとかしますという流れ。

### インベントリの設定
母艦Macにて、空き箱CentOSに指令を出すためのインベントリファイルの準備。

```
% mkdir ~/ansible
% cd ~/ansible
% echo '192.168.17.11' > host-saddle
```

で、一応、ここまでをテスト。普段、CentOSにsshするときは、vagrant sshを使うから、public_keyは気にしなくていいみたいだけど、ansibleからのsshの際には、必要。でも、そんなに頻繁に使うわけではないので、-kオプションで、パスワードを入力するようにしてる。

```
% ansible -u vagrant -k -i host-saddle 192.168.17.11 -m ping
SSH password: *****  <--- vagrant

paramiko: The authenticity of host '192.168.17.11' can't be established.
The ssh-rsa key fingerprint is e3569fea997763f91a1291ab91*********.
Are you sure you want to continue connecting (yes/no)?
yes
192.168.17.11 | success >> {
    "changed": false,
    "ping": "pong"
}

```


### playbookの用意
~/ansibleにsaddle.ymlという名前のファイルを作る。6つのやりたいことについては、それぞれ次のモジュールを使う。

(1) TimezoneをAsia/Tokyoへ **-> fileモジュール**
(2) yumでzshをインストール **-> yumモジュール**
(3) 母艦の~/.zshrcをコピー **-> copyモジュール**
(4) 標準のシェルをzshにする **-> commandモジュール**
(5) yumでemacsをインストール **-> yumモジュール**
(6) 母艦の~/.emacs.dをコピー **-> copyモジュール**

```:saddle.yml
---
- hosts: all
  sudo: yes
#  gather_facts: no
  tasks:
    - name: set timezone to Asia/Tokyo
      file: src=/usr/share/zoneinfo/Asia/Tokyo  dest=/etc/localtime state=link force=yes

    - name: install zsh
      yum: name=zsh state=installed
    - name: set zsh as default shell for vagrant user
      command: chsh -s '/bin/zsh' vagrant
    - name: copy .zsh file to vagrant home
      copy: src=~/.zshrc dest=~vagrant/.zshrc owner=vagrant group=vagrant mode="u=rw,g=r,o=r"

    - name: install emacs
      yum: name=emacs state=installed
    - name: copy .emacs.d directory to vagrant home
      copy: src=~/.emacs.d dest=~vagrant/ owner=vagrant group=vagrant
```
gather_factsのところは、結構時間掛かるので、コメントアウトしてもいいかも。

### playbookの実行
で、テストの時と同じように、-u, -k オプション付きで実行しちゃいます。

```
% ansible-playbook -i host-saddle saddle.yml -u vagrant -k
SSH password: *****  <--- vagrant

PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.17.11]

TASK: [set timezone to Asia/Tokyo] ********************************************
changed: [192.168.17.11]

TASK: [install zsh] ***********************************************************
changed: [192.168.17.11]

TASK: [set zsh as default shell for vagrant user] *****************************
changed: [192.168.17.11]

TASK: [copy .zsh file to vagrant home] ****************************************
changed: [192.168.17.11]

TASK: [install emacs] *********************************************************
changed: [192.168.17.11]

TASK: [copy .emacs.d directory to vagrant home] *******************************
changed: [192.168.17.11]

PLAY RECAP ********************************************************************
192.168.17.11              : ok=7    changed=6    unreachable=0    failed=0

```

イェイ！うまくいった！

でもこれ、もう一回流すと、本当は、changed=0(冪等性)になってほしいんだけど、(3)のcommandモジュールは毎回実行されちゃうので、changed=1になる。今回は、chshだから何回実行されてもいいんだけど、なんかかっこわるい。やりかた間違えてるのかな。。

今回は、鞍を用意するという目的は達成した（しょぼいけど。。）し、ansibleってこんな感じというのを掴めればよかったので、かなりシンプル。

でも、業務とかで本格的に使うのなら、[ベストプラクティス](https://docs.ansible.com/playbooks_best_practices.html)をしっかり読んだほうがいいのかな。TASKの意味を考慮した上でroleを設計し、、可変的なものは変数として抽出し、、システムを構成するサーバ毎に必要なroleを割り当て、、更にステージング用だったり、本番用だったり、、とか。なるほどなあとは思うけど、ここから自分たちに必要なものを選択するセンスが大切なのかなと。