chefで例えばapacheやnginxのconf一式( /etc/httpd/{conf,conf.d}
や /etc/nginx
配下)を作成させたい場合、
- template配下に大量のerbファイルが乱立してメンテコスト増
- 反映したい先のディレクトリ階層も違ったりして一つ一つtemplateで定義してると面倒
という問題があって、これをどうにかするために思いついた方法。
背景
chef入門のためとりあえず今までサーバ上で直接いじってたconfをリポジトリ管理にして、それをchefで反映させるところから始めるケースって多いんじゃないかと思います。
confファイルが1つ2つならいいんですが結構数ある場合や階層化させて体系化してる場合とか、まともに書くとrecipeの中身もtemplate配下もゴチャゴチャしてわかりにくい。
特に後から参画した方とか「このconf修正したいけど一々recipe見て該当erb探さなきゃいけない」のが面倒(直感的にわかりにくい)。
ただこれだけなんだけどchef導入の障害になってる気がしたので。
設定例
例えばnginxのcookbookを例とした場合、
attributeにこんな感じで基点となるディレクトリ名を定義しておいて、
default['nginx']['template_dir'] = "conf_web"
template配下に定義したディレクトリを作ってその配下に管理したいファイル一式を置いて、
$ tree nginx/templates/default/conf_web
nginx/templates/default/conf_web
├── conf.d
│ ├── ssl.conf
│ └── virtual.conf
├── fastcgi.conf
├── fastcgi_params
├── nginx.conf
├── scgi_params
├── conf.d
│ ├── server.key
│ └── server.crt
└── uwsgi_params
recipeはこんな感じ。
Chef::Config[:cookbook_path].each{|elem|
if File.exists?(File.join(elem, "/nginx/templates/default/", node['nginx']['template_dir']))
conf_dir = File.join(elem, "/nginx/templates/default/", node['nginx']['template_dir'])
Dir.chdir conf_dir
confs = Dir::glob("**/*")
confs.each do |t|
if File::ftype("#{conf_dir}/#{t}") == "file"
template "/etc/nginx/#{t}" do
owner "root"
group "root"
mode 00644
source "#{node['nginx']['template_dir']}/#{t}"
notifies :restart, "service[nginx]"
end
else
directory "/etc/nginx/#{t}" do
owner "root"
group "root"
mode 00755
end
end
end
end
}
これで対象サーバの /etc/nginx
配下に nginx/templates/default/conf_web
配下のファイルやディレクトリ一式が作成される。
templateじゃなくてcookbook_fileでも応用可能。
やっぱり黒魔術かなぁ。。。