Ansibleでローカルマシンの設定をした


[Ansible](http://www.ansible.com/home)はPython製のプロビジョニングツールです。

ちょうどBrewfileを変更しようとしたタイミングで、ローカルマシンの設定もAnsibleでやることにしました。

Python製といってもPythonの文法を覚える必要は無く、簡単なYAMLファイルを記述するだけですぐ使えます。

[ドキュメント](http://docs.ansible.com/)も大変読みやすく、この辺りはさすがPythonコミュニティだなぁと思います。

## 前提

- OS Xであること
- homebrewとAnsibleがインストールされていること

## ゴール

`ansible-playbook -K localhost.yml`を実行すると、以下の2つが実現されるようにします。

- 設定したbrewパッケージがインストールされること
- githubにあるdotfilesをチェックアウトし、ホームディレクトリにリンクすること

## インベントリーファイル

インベントリーファイルと呼ばれるファイルに対象ホストを列挙します。
ローカルマシンだけなので、localhostが記述されていればokです。

コマンドラインで指定もできますが、デフォルトで読むパスが決まっているので、そこに配置することにします。

``` text:/usr/local/etc/ansible/hosts
localhost
```

これだけだと何のために必要か分からないですが、Ansibleにターゲットとするホストの情報を教えるための仕組みのようです。

[ドキュメントのインベントリーファイルの章](http://docs.ansible.com/intro_inventory.html)にホストのグループ化などの方法が記載されています。

## 書き方

まず、設定ファイル(Playbook)の元となるファイルを記述します。

ホストグループやロールなど色々機能はありますが、所詮1ホストしか無いのでここでは使用しません。

``` localhost.yml
- hosts: localhost            # ホスト名
  connection: local           # ssh経由ではなくlocalhostで直接実行する
  gather_facts: no            # facts(ホスト情報?)の取得をしない
  tasks:
    - include: tasks/main.yml # タスクは別ファイルに記述 ここに直接書くこともできます
```

`tasks/main.yml`では以下の2つのファイルを`include`しています。

``` brew.yml
#- name: Update homebrew
#  homebrew: update_homebrew=yes upgrade_all=yes

- name: Tap homebrew repositories
  homebrew_tap: tap={{ item }}
  with_items:
    - sanemat/font
    - motemen/ghq
    - peco/peco

- name: Install homebrew packages
  homebrew: name={{ item.name }} install_options={{ item.options|default() }}
  with_items:
    - { name: 'autoconf' }
    - { name: 'automake' }
    - { name: 'pkg-config' }
    - { name: 'zsh' }
    - { name: 'vim', options: 'with-lua', 'override-system-vim' }
    - { name: 'macvim', options: 'override-system-vim', 'with-lua' }
    - { name: 'ctags' }
    - { name: 'git' }
    - { name: 'tmux' }
    - { name: 'brew-cask' }
    - { name: 'coreutils' }
    - { name: 'gibo' }
    - { name: 'rbenv' }
    - { name: 'ruby-build' }
    - { name: 'go' }
    - { name: 'ricty' }
    - { name: 'ghq' }
    - { name: 'peco' }

- name: Install homebrew cask packages
  homebrew_cask: name={{ item }}
  with_items:
    - vagrant
    - virtualbox
    - google-chrome
    - google-japanese-ime
    - google-drive
    - skype
    - appcleaner
    - flash-player
    - xquartz
    - kobito
```

``` dotfiles.yml
- name: Checkout my dotfiles
  git: 
    repo: https://github.com/makiton/dotfiles.git
    dest: ~/dotfiles

- name: Create symlinks
  file:
    src: ~/dotfiles/{{ item }}
    dest: ~/{{ item }}
    state: link
    force: yes
  with_items:
    - .tmux.conf
    - .zshrc
    - .gitconfig
    - .gitignore
    - .vimrc
    - .vim
```

`name`はタスクの名前で、実行時にプログレスとして表示されるので分かりやすい名前をつけておきましょう。

`homebrew`や`file`というのがモジュールと呼ばれる各タスクの本体です。
`モジュール名: arg1=arg arg2=arg ...`の形で指定します。

`with_items`は繰り返しの指定で、要素を`{{ item }}`に展開しながら要素の数だけタスクを実行します。

上記のすべてのファイルは[makiton/playbook-osx](https://github.com/makiton/playbook-osx)に置いてあります。

## さいごに

やっては見ましたがそもそもlocalhostの設定なんて年に1度程度だし、Ansible本来の良い所はわかりづらいかも知れません。

Chefに挫折している時たまたま同僚に教えてもらってすごく手触りが良かったので、個人的に転職を控えていてその時役に立つだろうと思い、試しにやってみました。

存在は知ってはいたけどいきなり本番環境で使うわけにもいかないし…と思っていたので、練習にもなって良かったです。

引数のフォーマットなどが分からない時はソースコードに当たってみたんですが、Pythonの知識はほとんど無いものの障害なく読めました。

[ansible/ansible-modules-core](https://github.com/ansible/ansible-modules-core)にmoduleの実装があります。

サンプルがほしい時は[ansible/ansible-examples](https://github.com/ansible/ansible-examples)も参考になります。