chef-soloでcookbookを作成する

以前からJenkinsさんをchefで立ち上げるところまで自動化したのですが、
Jenkinsさんの自動起動が設定されていなかった。
ドキュメントを流し読みしてみても、Jenkinsさんの自動起動設定がない。
じゃあそういうレシピ作成してみよかと思ったのですが、数カ月前ということもあり、完全に失念!

ということで、chefのcookbook作成方法のメモです。

まず、環境を作る。

git clone https://github.com/shiraji/chef-repo.git
cd $HOME/chef-repo
bash chef_setup.sh
これで問題なければ、今回使うchefやknifeが入る。
chef-soloなので、knifeの設定(knife configure)をせずに突き進む。

以前にも書いたと思うけど、ざっくり構成についておさらい。

chef-repo/
├── cookbooks --- 人が作ったcookbooksを保持
├── nodes --- 実行される各サーバ固有の設定を保持
├── roles --- cookbook利用時の設定値を保持
└── site-cookbooks --- 自分が作成したcookbookを保持
├── addusers --- 自作ユーザ追加cookbook
└── server_settings --- 自作サーバの基本設定のcookbook
nodesとrolesはかなり重要で、この2つを意識したcookbookを作れば、拡張性が高くなる。

実際にcookbookを作成してみる。

cd $HOME/chef-repo/site-cookbooks/
knife cookbook create autorun_settings -o .
knifeが色々揃えてくれた結果がこれ
site-cookbooks/
└── autorun_settings
├── CHANGELOG.md
├── README.md
├── attributes --- attributeを設定する。default.rbがデフォルトの値
├── definitions
├── files
│ └── default
├── libraries
├── metadata.rb
├── providers
├── recipes
│ └── default.rb --- デフォルトのrecipe
├── resources
└── templates
└── default
Hello worldしてみる。

デフォルトのrecipe(recipes/default.rb)に以下を書き込む。

puts "Hello World"
これだけでほぼ終わりなのだけど、せっかくなので、nodes, rolesを設定する。

まずはrole。$HOME/chef-repo/roles/にjenkins_autorun.jsonを作成する。
本当はここで、knife role createとかするべきなんだけど、knifeの設定してないしーということで簡単なスクリプト作成したので、それを利用して、作成する。

cd $HOME/chef-repo/roles/
bash new_role.sh jenkins_autorun.json
new_role.shはsedでテンプレートファイルの中身を変更し、それをファイルに保存している。
#!/bin/sh

if [ $# -ne 1 ]; then
echo "No role name"
exit 1
fi

_role_name=$1

cat role_template.json | sed -e "s/NAME/${_role_name}/g" > ./${_role_name}.json

role_template.jsonはknife create roleすると出来るべきroleファイル
{
"name": "NAME",
"description": "",
"json_class": "Chef::Role",
"default_attributes": {
},
"override_attributes": {
},
"chef_type": "role",
"run_list": [

],
"env_run_lists": {
}
}

上記のコマンド叩いて、出来るのがこのrole。(コピペするだけでも問題ない。)
{
"name": "jenkins_autorun",
"description": "",
"json_class": "Chef::Role",
"default_attributes": {
},
"override_attributes": {
},
"chef_type": "role",
"run_list": [

],
"env_run_lists": {
}
}

今のところ、attributesなどはないので、設定せず、run_listに先程作成したcookbookを設定する。
{
"name": "jenkins_autorun",
"description": "",
"json_class": "Chef::Role",
"default_attributes": {
},
"override_attributes": {
},
"chef_type": "role",
"run_list": [
"recipe[autorun_settings]"
],
"env_run_lists": {
}
}
次にnode
run_listに上記で作成したroleを指定する。
{
"run_list": [
"role[jenkins_autorun]"
]
}
実行で必要な設定ファイル(chef-repo/solo.rb)はこんな感じ。
le_cache_path           "#{ENV['HOME']}/chef-repo"
data_bag_path "#{ENV['HOME']}/chef-repo/data_bags"
encrypted_data_bag_secret "#{ENV['HOME']}/chef-repo/data_bag_key"
cookbook_path [ "#{ENV['HOME']}/chef-repo/site-cookbooks",
"#{ENV['HOME']}/chef-repo/cookbooks" ]
role_path "#{ENV['HOME']}/chef-repo/roles"
$HOME直下に置いてあると想定されている。違う所に置いてある場合は、このファイルを変更すること。
拡張子で一目瞭然だけど、solo.rbはrubyファイル。$HOMEは使えないので注意。

それでは実行

cd $HOME/chef-repo
chef-solo -c solo.rb -j nodes/jenkins_autorun.json
実行結果
Starting Chef Client, version 11.6.0
Compiling Cookbooks...
Hello World
Converging 0 resources
Chef Client finished, 0 resources updated
これで、Hello Worldはできたので、今回の目的であるjenkinsのサービスの自動起動をしてみる。
chkconfig jenkins onを実行すればいい。
resourcesというものがchefで実行されるコマンド。詳細はここhttp://docs.opscode.com/resource.html
このresourcesとrubyの文法を駆使してrecipeを作成していく。
簡単なlinuxのコマンドのため、resourcesはexecuteを利用する。
chef-repo/site-cookbooks/autorun_settings/recipes/default.rbに以下を記載する
execute "autorun" do
command "chkconfig jenkins on"
action :run
end
ただ、これだと、jenkinsのみのcookbookになってしまう。そこでattributeを設定し、roleで指定できるようにする。
まずはデフォルトのattributeを作成する。
chef-repo/site-cookbooks/autorun_settings/attributesにdefault.rbを作成。中身は以下。
default[:autorun][:ons] = ["jenkins"]
これを使うrecipeはこんな感じ。
node[:autorun][:ons].each do |on|
if !on.empty?
execute "autorun on" do
command "chkconfig #{on} on"
action :run
end
end
end
実際に実行してみると
Starting Chef Client, version 11.6.0
Compiling Cookbooks...
Converging 1 resources
Recipe: autorun_settings::default
* execute[autorun on] action run
- execute chkconfig jenkins on

Chef Client finished, 1 resources updated
これでもまだ、拡張性がないので、autorunの設定のON、OFFができるようにする。
まずデフォルトの設定を以下にする。
default[:autorun][:ons] = []
default[:autorun][:offs] = []
デフォルトのrecipeを以下に
node[:autorun][:ons].each do |on|
if !on.empty?
execute "autorun on" do
command "chkconfig #{on} on"
action :run
end
end
end

node[:autorun][:offs].each do |off|
if !off.empty?
execute "autorun off" do
command "chkconfig #{off} off"
action :run
end
end
end

ここで、roleでoverride_attributesを設定する。chef-repo/roles/jenkins_autorun.jsonを以下のようにする。
{
"name": "jenkins_autorun",
"description": "",
"json_class": "Chef::Role",
"default_attributes": {
},
"override_attributes": {
"autorun": {
"ons": ["jenkins"]
}

},
"chef_type": "role",
"run_list": [
"recipe[autorun_settings]"
],
"env_run_lists": {
}
}
実行結果(上記と同じ)
Starting Chef Client, version 11.6.0
Compiling Cookbooks...
Converging 1 resources
Recipe: autorun_settings::default
* execute[autorun on] action run
- execute chkconfig jenkins on

Chef Client finished, 1 resources updated
これで完了。

■注意点■
私は今CentOSの環境のみしかないので、chkconfigが使えないubuntuとか気にしていない。
必要な場合はOS別のコマンドを作成すればいいと思う。