Chef初心者がChef Solo+Vagrantでレシピを書いていく方法

chef-solo+Vagrantでレシピを書いていくすごい個人的な方法です。

【前提】

* Chefレシピ書き初心者
* ChefとVagrantはインストール済み
* vagrant provision or vagrant up --provisionでプロビジョニングする
* 動作を確認しながらプロビジョニングしたい
* 自前のレシピを作成する(外部Cookbookは使用しない)

# フロー

1. knife soloコマンドでChefディレクトリのひな形を作成する
2. saharaでサンドボックス上で作業する
  1. Chefのレシピを書く
  2. vagrant provision
  3. 書いたレシピが正常に働いでいることを確認
  4. 間違っていたりしたら、vagrant sandbox rollback
  5. 問題なかったら、vagrant sandbox commit
3. 1~5を繰り返す

# 必要なツール

vagrant-omnibusとsahara、knife-soloをインストール。

```
$ vagrant plugin install vagrant-omnibus
$ vagrant plugin install sahara
$ /opt/chef/embedded/bin/gem install knife-solo
```

gemでchefをインストールしている場合、"/opt/chef/embedded/bin/"はいらない。

# Sandbox環境で作業する

やり直したい衝動が頻繁に襲ってくるので、saharaを使ってSandbox上で作業する。

```
$ cd path/to/vagrant/dir
$ vagrant up
$ vagrant sandbox on
```

saharaのコマンドは、"on", "off", "status", "commit", "rollback"とシンプル。

履歴は保存されないので、一度commitするとその前には戻れないので注意。

# Chefディレクトリの準備

knife-soloコマンドを使って、Chefディレクトリを作成します。

```
$ cd path/to/vagrant/dir
$ knife solo init .
$ knife cookbook create hoge -o site-cookbooks
```

作成したcookbookをgitリポジトリとして管理します。

```
$ cd site-cookbooks/hoge
$ git init
$ git add .
$ git commit -m  "Initial commit."
```

作成されたディレクトリ構成は以下

```
├── Berksfile
├── Vagrantfile
├── cookbooks
├── data_bags
├── environments
├── nodes
├── roles
└── site-cookbooks
    └── hoge
        ├── CHANGELOG.md
        ├── README.md
        ├── attributes
        ├── definitions
        ├── files
        ├── libraries
        ├── metadata.rb
        ├── providers
        ├── recipes
        ├── resources
        └── templates
```

# vagrant provisionでプロビジョニングするためにVagrantfileを編集する

Vagrantfileに以下を追記します。

```ruby:Vagrantfile
  config.omnibus.chef_version = :latest
  config.vm.provision "chef_solo" do |chef|
    chef.cookbooks_path = "./site-cookbooks"
    chef.run_list = ["hoge"]
  end
```

これで、vagrant provision or vagrant up --provisionをすると、Chefがゲスト側になかった場合はインストールされて、hogeに書いたレシピでプロビジョニングが実行されます。

# レシピを書く

site-cookbooks/hoge/recipes/default.rbにレシピを書いていきます。

```ruby:site-cookbooks/hoge/recipes/default.rb
package "zsh" do
  action :install
end
```

zshをインストールする内容を書きました。目的の内容をここにどんどん記載していきます。詳しいレシピの書き方はここでは説明しません、ググってください。

僕の場合はレシピを書くことにまだ慣れていないため、このdefault.rbにどんどん追記していってはvagrant provision、うまくいったらcommit、ダメだったらrollbackします。

# レシピを分割する

内容が膨らんできて、レシピを分割したい場合は、site-cookbooks/hoge/recipesに新しいrubyファイルを追加します。例えば、vim-build.rbを作成してみます。

```ruby:site-cookbooks/hoge/recipes/vim-build.rb
%w{mercurial　lua5.2 liblua5.2-dev gettext libncurses5-dev libacl1-dev libgpm-dev libperl-dev python-dev python3-dev ruby-dev}.each do |pkg|
  package pkg do
    action :install
  end
end

bash "build vim" do
#  not_if "vim --version | grep 7.4"
  cwd /tmp
  code <<-EOH
    hg clone https://vim.googlecode.com/hg/ vim
    cd vim
    ./configure --with-features=huge --enable-perlinterp --enable-pythoninterp --enable-python3interp --enable-rubyinterp --enable-luainterp --enable-fail-if-missing
    make
    make install
  EOH
end
```

このままでは実行されないので、Vagrantfileに書いたレシピを追加します。

```ruby:Vagrantfile
  config.omnibus.chef_version = :latest
  config.vm.provision "chef_solo" do |chef|
    chef.cookbooks_path = "./site-cookbooks"
    chef.run_list = ["hoge", "hoge::vim-build"]
  end
```

\<cookbook名\>::\<file名\>で指定します。"::<file名>"の指定がない場合は、defaultが実行されます。

これで、一つのcookbook内で複数のrecipeを使用できます。install-hoge, setup-hogeなどと分けるといいのかもしれません。

cookbook名を変えれば複数cookbookも使えます。多分規模に応じて選択する感じです。

# さいごに

さいごに言うのもあれですが、Berkshelfを使用していません。Berkshelfを使ったものは他の記事を参考にしてください。