読者です 読者をやめる 読者になる 読者になる

Chefでrbenvを使ってRubyをインストールする

Chefでrbenvを使ってRubyをインストールする方法のメモ。

関連記事

レシピの解説

今回は ChefとVagrantによる開発環境の構築 で作成したレシピを使って解説する。完成したレシピはここに置いてあるので適宜参照のこと。

rbenv/README.md at master · sstephenson/rbenv を参考に、まずはrbenvをインストールするためのレシピを作成する。

まず、rbenvをgit cloneしてユーザーvagrantの$HOMEに置く。ディレクトリは.rbenvという名前にする。

git "/home/vagrant/.rbenv" do
  repository "https://github.com/sstephenson/rbenv.git"
  revision   "master"
  user       "vagrant"
  group      "vagrant"
  action     :sync
end

ディレクトリ~/.rbenv/plugins/を作成して、このディレクトリにruby-buildをgit cloneする。

directory "/home/vagrant/.rbenv/plugins" do
  owner  "vagrant"
  group  "vagrant"
  action :create
end

git "/home/vagrant/.rbenv/plugins/ruby-build" do
  repository "https://github.com/sstephenson/ruby-build.git"
  revision   "master"
  user       "vagrant"
  group      "vagrant"
  action     :sync
end

bashの設定ファイルを用意する。

%w{.bash_profile .bashrc}.each do |filename|
  template filename do
    owner  "vagrant"
    group  "vagrant"
    mode   "0644"
    path   "/home/vagrant/#{filename}"
    source "#{filename}.erb"
  end
end

.bash_profileには、rbenv/README.md at master · sstephenson/rbenvに記載されている通り、rbenvを使用するために必要な設定を書いておく必要がある。

export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

次に、rbenv.shというスクリプトをホームディレクトリに作成する。このファイルがなぜ必要なのかについてはrbenv.shの必要性についてを参照のこと。

template "rbenv.sh" do
  owner  "vagrant"
  group  "vagrant"
  path   "/home/vagrant/rbenv.sh"
  source "rbenv.sh.erb"
end

Ruby のインストールに必要なopenssl-develをpackageでインストールする。

package "openssl-devel" do
  action :install
end

Rubyをインストールする。ただ単にrbenv installするのではなく、その直前でrbenv.shを実行するようにする。こうする理由はrbenv.shの必要性についてを参照のこと。また、既にインストール済みの場合はスキップするようnot_ifでファイルの存在を確認する。

bash "rbenv install 2.0.0-p353" do
  user   "vagrant"
  cwd    "/home/vagrant"
  code   "source rbenv.sh; rbenv install 2.0.0-p353"
  action :run
  not_if { ::File.exists? "/home/vagrant/.rbenv/versions/2.0.0-p353" }
end

rehashする。rehashする際にも直前でrbenv.shを実行する。

bash "rbenv rehash" do
  user   "vagrant"
  cwd    "/home/vagrant"
  code   "source rbenv.sh; rbenv rehash"
  action :run
end

2.0.0-p353をglobalに設定する。同様にrbenv.shを実行。

bash "rbenv global 2.0.0-p353" do
  user   "vagrant"
  cwd    "/home/vagrant"
  code   "source rbenv.sh; rbenv global 2.0.0-p353"
  action :run
end

gemをインストールする際にも直前でrbenv.shを実行する必要がある。

bash "bundler" do
  user   "vagrant"
  cwd    "/home/vagrant"
  code   "source rbenv.sh; gem install bundler"
  action :run
  not_if { ::File.exists? "/home/vagrant/.rbenv/shims/bundle" }
end

rbenv.shの必要性について

rbenv.sh のなかには、.bash_profile.erbに記載したのとほぼ同様の、rbenvを使用するために必要な設定が記載されている。

プロビジョニングを行わず、vagrant init -> vagrant upした直後にvagrant sshしてVMにログインして、PATHをechoすると、以下のような結果になった。

[vagrant@vagrant-centos ‾]$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/vagrant/bin
%

このVMに対して、以下のようなレシピを実行して、それぞれPATHをechoした結果をコメントとして記すと以下のようになる。

bash "vagrant" do
  user   "vagrant"
  code   "echo $PATH > /home/vagrant/path_vagrant"
  action :run
end
# $ cat path_vagrant
# /sbin:/bin:/usr/sbin:/usr/bin:/opt/chef/embedded/bin:/opt/chef/embedded/bin:/usr/local/sbin:/usr/local/bin

bash "root" do
  user   "root"
  code   "echo $PATH > /home/vagrant/path_root"
  action :run
end
# $ cat path_root
# /sbin:/bin:/usr/sbin:/usr/bin:/opt/chef/embedded/bin:/opt/chef/embedded/bin:/usr/local/sbin:/usr/local/bin

bash "root export" do
  user   "root"
  code   "export PATH=/home/vagrant:$PATH; echo $PATH > /home/vagrant/path_root_export"
  action :run
end
# $ cat path_root_export
# /home/vagrant:/sbin:/bin:/usr/sbin:/usr/bin:/opt/chef/embedded/bin:/opt/chef/embedded/bin:/usr/local/sbin:/usr/local/bin

bash "root again" do
  user   "root"
  code   "echo $PATH > /home/vagrant/path_root_again"
  action :run
end
# $ cat path_root_again
# /sbin:/bin:/usr/sbin:/usr/bin:/opt/chef/embedded/bin:/opt/chef/embedded/bin:/usr/local/sbin:/usr/local/bin

Chef実行中は「/opt/chef/embedded/bin」などのChefを実行するために必要なPATHが設定されている。ChefはRubyのgemであり、/opt/chef/embedded/bin にはChefの実行するのに使用されるRubyの実行ファイルなどが格納されている。

bash "root export" do
  user   "root"
  code   "export PATH=/home/vagrant:$PATH; echo $PATH > /home/vagrant/path_root_export"
  action :run
end
# $ cat path_root_export
# /home/vagrant:/sbin:/bin:/usr/sbin:/usr/bin:/opt/chef/embedded/bin:/opt/chef/embedded/bin:/usr/local/sbin:/usr/local/bin

上記のように、PATHをexportすると、そのResource実行中はPATHを変更できるが、次のResourceを実行する際にはPATHは元に戻ってしまっている。bash ResourceではPATHやその他の環境変数を指定することもできる(詳細はbash - Chef Docs を参照のこと)が、今回はrbenvを実行するたびに、その直前でrbenv.shを実行することにした。

参考文献

入門Chef Solo - Infrastructure as Code

入門Chef Solo - Infrastructure as Code