rbenvをインストールするRecipeの作成
まずは、install_rbenv.rbのRecipeを作成していきます。rbenvのインストール手順は大まかに以下のようになります(詳細についてはrbenvのgithubの公式ページを参照してください)。
- Rubyのインストールにあたってビルドに必要な依存パッケージをインストールする
- rbenvとrubyインストール用のプラグインをインストールする
- rbenv用の環境変数を設定する
この流れに沿って、rbenvをインストールするRecipeを作成します。まずは、attributeにrbenvのインストール先ディレクトリとrbenvを使ってインストールするRubyのバージョンを定義します。
default[:rbenv][:install_rbenv][:dir] = '/opt/rbenv' # rbenvのインストール先 default[:rbenv][:install_ruby][:version] = '2.1.1' # rbenvを使ってインストールするRubyのバージョン
続いて、rbenv自体をインストールするRecipeを作成します。
# attributes定義より、rbenvをインストールするディレクトリ情報を取得します
install_dir = node[:rbenv][:install_rbenv][:dir]
# 1. packageリソースを使ってRubyのビルドに必要なパッケージをインストールします
%w( gcc-c++ glibc-headers openssl-devel readline readline-devel zlib zlib-devel ).each do |pkg|
package pkg do
action :install
end
end
# 2-1. gitリソースを使ってrbenv本体をインストール先ディレクトリに配置します
git 'install rbenv' do
user 'root'
destination install_dir
repository 'https://github.com/sstephenson/rbenv.git'
not_if "ls #{install_dir}"
end
# directoryリソースを使ってrbenvのプラグインインストール用のディレクトリを作成します
directory "#{install_dir}/plugins" do
owner 'root'
group 'root'
mode 0644
action :create
end
# 2-2. gitリソースを使ってrbenvのプライグインをインストールします
git 'install ruby-build' do
user 'root'
destination "#{install_dir}/plugins/ruby-build"
repository "https://github.com/sstephenson/ruby-build.git"
action :checkout
not_if "ls #{install_dir}/plugins/ruby-build"
end
# 3. bashリソースを使ってrbenv用の環境変数設定スクリプトを配置します
env_file = '/etc/profile.d/rbenv.sh'
bash 'set rbenv environment' do
user 'root'
code <<-EOH
echo 'export RBENV_ROOT="#{install_dir}"' >> #{env_file}
echo 'export PATH="$RBENV_ROOT/bin:$PATH"' >> #{env_file}
echo 'eval "$(rbenv init -)"' >> #{env_file}
EOH
not_if "ls #{env_file}"
end
最後に、Rubyをインストールしてバージョンを切り替えるRecipeを作成します。
# attributes定義より、インストールするRubyのバージョン情報を取得します
install_version = node[:rbenv][:install_ruby][:version]
install_dir = node[:rbenv][:install_rbenv][:dir]
rbenv_path = "RBENV_ROOT=#{install_dir} #{install_dir}/bin"
# rbenvを使ってRubyのインストールを実行します
bash 'install ruby' do
user 'root'
code <<-EOH
#{rbenv_path}/rbenv install #{install_version}
#{rbenv_path}/rbenv rehash
#{rbenv_path}/rbenv global #{install_version}
EOH
only_if do
`#{rbenv_path}/rbenv install -l | grep -wc #{install_version}`.to_i > 0 &&
`#{rbenv_path}/rbenv versions | grep -wc #{install_version}`.to_i == 0
end
end
# インストールしたRubyを有効にします
bash 'switch ruby version' do
user 'root'
code <<-EOH
#{rbenv_path}/rbenv rehash
#{rbenv_path}/rbenv global #{install_version}
EOH
only_if "#{rbenv_path}/rbenv versions | grep -w #{install_version}"
end
Recipeの作成後、chef-soloを実行する際に必要な設定ファイルであるrunlistと設定ファイルを作成します。runlistには実行対象のRecipeと実行順序を定義します。ここではrunlistのファイル名はnode.json、設定ファイルはsolo.rbとしてchef-soloを実行します(chef-soloの実行はRubyのコンパイルに少し時間がかかります)。
まずrbenvをインストールして、次にrbenvを使ってRubyをインストールするようにrunlistとchef-soloを実行するための定義ファイルを作成します。
{
"run_list": [
"recipe[rbenv::install_rbenv]",
"recipe[rbenv::install_ruby]"
]
}
cookbook_path ['/home/tis/chef-repo/cookbooks'] # 実行するCookbookの在処を定義します log_level :info
$ chef-solo -c solo.rb -j node.json ...chef-soloの実行... ...Chef Run complete in ~のメッセージを確認する... $ ruby -v ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-linux]
これで、Chefを使ってrbenvをインストールすることができました。しかし、ここではいくつかの問題があります。
- Recipe内に大量のexecuteやbashリソースを使っているため、Recipeを見た際に何をやりたいかが把握しづらい
- Rubyビルド用の依存パッケージのインストールがRedHat系Linuxでしか動かない
このようにRecipeに書くコード量が多くなり、見通しが悪くなってしまった場合には、独自のResourceを定義して使用すると、executeやbashなどのResourceをRecipe内で使うのを防ぎ、Recipeをすっきりさせることが可能です。また、外部Resource化してRecipeの整理を行うと、Recipe内で実施すべきことを明確にできます。
今回の場合は、インストールのRecipeでRubyビルド用パッケージのインストールとrbenvのインストールが混在しているため、これらを分割します。分割の方針としては、Rubyビルド用パッケージのインストールはRecipeに残し、rbenvのインストールやRubyのビルドは外部Resource定義に移動させます。
