SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

近未来の技術トレンドを先取り! 「Tech-Sketch」出張所

構成管理ツール「Chef」の一歩進んだ使い方 ―独自のResourceを定義する―

近未来の技術トレンドを先取り! 「Tech-Sketch」出張所 第12回

  • X ポスト
  • このエントリーをはてなブックマークに追加

Provider定義

 Resourceで定義したactionのinstall_rbenvとinstall_rubyの内容を実装します。処理の内容は、独自Resource導入前に作成したRecipeのinstall_rbenv.rbとinstall_ruby.rbの内容とほぼ同じです。異なる箇所は、独自Resource導入前はインストールディレクトリやRubyのバージョンをattributeに定義していたものがResourceに定義したattributeを使うように修正した点です。もし、プラットフォーム差異が発生するような場合は、Provider内でプラットフォームの差異を吸収するとよりよいでしょう。

providers/settings.rb
# Resourceで定義したinstall_rbenv actionを実装します
# Providerの action (Resourceで定義したactionのシンボル) ブロック内で処理内容を実装します
action :install_rbenv do
  # Resource定義のattributeで指定したパラメータはnew_resource.(attribute名)で取得できます
  install_dir = "#{new_resource.install_dir}/rbenv"
  env_file = '/etc/profile.d/rbenv.sh'

  # 1. 依存パッケージのインストール(install_rbenv.rbレシピからの移植)
  # 依存パッケージのインストールはRecipe内で定義します

  # 2-1. gitリソースを使ってrbenv本体をインストール先ディレクトリに配置します(install_rbenv.rbレシピからの移植)
  git 'install rbenv' do
    user 'root'
    destination install_dir
    repository 'https://github.com/sstephenson/rbenv.git'
    not_if "ls #{install_dir}"
  end

  # directoryリソースを使ってrbenvのプラグインインストール用のディレクトリを作成します(install_rbenv.rbレシピからの移植)
  directory "#{install_dir}/plugins" do
    owner 'root'
    group 'root'
    mode 0644
    action :create
  end

  # 2-2. gitリソースを使ってrbenvのプライグインをインストールします(install_rbenv.rbレシピからの移植)
  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. rbenv用の環境変数設定スクリプトを配置します(install_rbenv.rbレシピからの移植)
  bash 'set rbenv to 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
end

# install_ruby actionを実装します
action :install_ruby do
  # Resource定義のattributeで指定したパラメータはnew_resource.(attribute名)で取得できます
  install_version = new_resource.version
  install_dir = "#{new_resource.install_dir}/rbenv"
  rbenv_path = "RBENV_ROOT=#{install_dir} #{install_dir}/bin"

  # rbenvを使ってRubyをインストールします(install_ruby.rbレシピからの移植)
  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

  # インストールしたRubyを有効にします(install_ruby.rbレシピからの移植)
  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
end

定義したResourceを使用したRecipe

 定義したResourceをRecipeで使用する際のResource名は「cookbook名_Resourceファイル名」です。今回の場合は「rbenv_settings」がResource名です。LWRPを使う前後でRecipeの内容を比較すると、格段に分かりやすくなっていると思います。

recipes/default.rb
# 依存パッケージのインストールをRedHat系とDebian系で分岐
case node[:platform]
when 'redhat', 'centos'
  packages = %w( gcc-c++ glibc-headers openssl-devel readline readline-devel zlib zlib-devel )
when 'debian', 'ubuntu'
  packages = %w( autoconf bison build-essential libssl-dev libyaml-dev libreadline6 libreadline6-dev zlib1g zlib1g-dev )
end

packages.each do |pkg|
  package pkg do
    action :install
  end
end

# rbenvのインストール
# Resource定義でinstall_rbenvをデフォルトactionにしたので、actionは指定する必要はありません
rbenv_settings 'install rbenv'

# Ruby 2.1.1をインストールして有効にする
rbenv_settings 'install ruby' do
  version '2.1.1'
  action :install_ruby
end

# 試しにRuby 2.1.0を追加でインストールして有効にしてみる
rbenv_settings 'install ruby' do
  version '2.1.0'
  action :install_ruby
end

 このRecipeを実行したらrbenvを使ってRubyの2.1.1と2.1.0をインストールし、最終的に反映させたRuby 2.1.0が有効になっているかと思います。これで独自のResourceを定義してRecipeを作成し、Chefを実行することができました。

LWRPを使用しているCookbookの例

 最後に、LWRPを使用しているCookbookの例をご紹介します。

 Opscode CommunityではさまざまなCookbookが提供されています。これらのCookbookでは、LWRPや今回は紹介できなかったChefの機能であるLibrary(Rubyのロジックをメソッド単位で外だしする機能)がよく使われており、Recipeに直接関係のないようなロジックはRecipe外で定義され、Recipeが見やすくなるように工夫されています。コミュニティのCookbookを使ったり、参考にする際にはLWRPを意識してみてください。

 ※執筆時点での情報のため、変更される可能性があります

まとめ

 今回はRubyのバージョン管理ツールであるrbenvのCookbookを作成し、LWRPを使って見通しの悪いRecipeをリファクタリングし、見通しのよいRecipeを作成してみました。見通しのよいRecipeを作成すると、どのような環境を構築したいかがより明確になります。また、LWRPを使うことで、別のCookbookからも利用しやすくなり、再利用性も向上します。

 これまでChefを使った経験はあるけれど、LWRPを避けていた方はこれを機にLWRPを使ってみてはいかがでしょうか。これからChefを始める方も、Recipeが膨大になってきた際にはLWRPの導入を検討してみてください。

 次回は、ScalaのWebアプリケーションフレームワーク「Play Framework」入門の続編です。お楽しみに!

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
近未来の技術トレンドを先取り! 「Tech-Sketch」出張所連載記事一覧

もっと読む

この記事の著者

秋穂 賢(TIS株式会社)(アキホ スグル)

TIS株式会社 戦略技術センター所属。TIS入社後の4年間、メインフレームを用いた大規模基幹システムのシステム管理や運用業務に従事。その後OSSの世界に飛び込み、推奨OSSミドルウェアスタック「ISHIGAKI Template」の開発やデザイン指向クラウドオーケストレーションソフトウェア「CloudConductor」の開発を経て、現在はOSSサポートビジネス立ち上げに携わっている。また、OSSの活動の一環でJobSchedulerと出会い、日本JobSchedulerユーザ会でも活動をしている。TISでは技術情報をブログ「Tech-Sketch」にて発信中。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/7767 2014/05/23 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング