serverspecのテストケースを育ててみた
前回の記事で作成したserverspecのテストケースを育ててみました。Ruby on Railsチュートリアルの写経を始めました - m-namikiの日記のときに作成したレシピを対象にします。レシピはこんなことをやっていました。
- iptablesの停止、無効化
- epel、remiをyumのリポジトリに追加
- sqlite-develのインストール
- rbenvでruby1.9.3-p545のインストール
- gemでrbenv-rehash、rails3.2.14のインストール
で、追加したテストケースはこちら。
# package for rails3-tutorial describe package('sqlite-devel') do it { should be_installed } end # ruby versions describe command('ruby -v') do it { should return_stdout /ruby 1\.9\.3p545.+/ } end # for gem packages describe package('rbenv-rehash') do it { should be_installed.by('gem') } end describe package('rails') do it { should be_installed.by('gem').with_version('3.2.14') } end
epel、remiに関しては最初に書いたときに入れていたので割愛します。で、さっそく実行してみると
C:\Users\m-namiki\Documents\20_vagrant\rails3_tutorial>rake spec C:/Ruby193/bin/ruby.exe -S rspec spec/default/base_spec.rb ..........FFF Failures: 1) Command "ruby -v" should return stdout /ruby 1\.9\.3p545.+/ Failure/Error: it { should return_stdout /ruby 1\.9\.3p545.+/ } sudo ruby -v ruby 1.8.7 (2011-06-30 patchlevel 352) [x86_64-linux] expected Command "ruby -v" to return stdout /ruby 1\.9\.3p545.+/ # ./spec/default/base_spec.rb:36:in `block (2 levels) in <top (required)>' 2) Package "rbenv-rehash" should be installed Failure/Error: it { should be_installed.by('gem') } sudo gem list --local | grep -w -- \^rbenv-rehash expected Package "rbenv-rehash" to be installed # ./spec/default/base_spec.rb:41:in `block (2 levels) in <top (required)>' 3) Package "rails" should be installed Failure/Error: it { should be_installed.by('gem').with_version('3.2.14') } sudo gem list --local | grep -w -- \^rails | grep -w -- 3.2.14 expected Package "rails" to be installed # ./spec/default/base_spec.rb:45:in `block (2 levels) in <top (required)>' Finished in 27.6 seconds 13 examples, 3 failures Failed examples: rspec ./spec/default/base_spec.rb:36 # Command "ruby -v" should return stdout /r uby 1\.9\.3p545.+/ rspec ./spec/default/base_spec.rb:41 # Package "rbenv-rehash" should be installe d rspec ./spec/default/base_spec.rb:45 # Package "rails" should be installed C:/Ruby193/bin/ruby.exe -S rspec spec/default/base_spec.rb failed
残念、失敗!エラーメッセージを見るとsudo
しているので、rbenvでインストールしたrubyのバージョンが違ったり、gemで認識されていなかったりするようです。なのでまずはvagrantユーザで実行しているruby
とgem
はどこを見ているのか確認してみます。
[vagrant@localhost ~]$ which ruby /opt/rbenv/shims/ruby [vagrant@localhost shims]$ which gem /opt/rbenv/shims/gem
なるほど、ならばリソースタイプがcommandの場合はこのパスを追加してあげれば良さそうですが、packageの場合はどうしよう。答えは公式ドキュメントに書いてありました。ページ下段の方にあるBlock scoped PATH environment variableを読んでみるとブロック内でPATHを指定することができるようです。なので以下のように書き換えてみました。
# ruby versions describe command('ruby -v') do let(:path) { '/opt/rbenv/shims' } it { should return_stdout /ruby 1\.9\.3p545.+/ } end # for gem packages describe package('rbenv-rehash') do let(:path) { '/opt/rbenv/shims' } it { should be_installed.by('gem') } end describe package('rails') do let(:path) { '/opt/rbenv/shims' } it { should be_installed.by('gem').with_version('3.2.14') } end
同じ設定を3回書いてるのがちょっとアレですが、これで実行してみます。
C:\Users\m2-namiki\Documents\20_vagrant\rails3_tutorial>rake spec C:/Ruby193/bin/ruby.exe -S rspec spec/default/base_spec.rb ............... Finished in 29.69 seconds 15 examples, 0 failures
今度は無事に成功しました。公式ドキュメントは隅々まで読まなきゃダメですね。。。あとはChefでrbenvを使ってRubyをインストールするCookbookを書いた | ひげろぐを参考にさせていただき、最終的なテストケースはこんな感じになりました。
serverspecをvagrantと連携させるためのプラグイン(vagrant-serverspec)もあるそうなので、今度はこちらも試してみようと思います。
serverspecを書いてみた
ここら辺を調べてるときにチラチラと見かけたserverspecが気になっていたので調べてみました。serverspec - Homeはサーバの状態・設定をテストするためのプロダクト、のようです。なので、Railsチュートリアル環境に対してのテストを書いてみたいと思います。
serverspecのインストール
serverspecはgemで提供されているので、まずはホームディレクトリにGemfileを作成します。
// ~/Gemfile source 'https://rubygems.org' gem "serverspec", "1.0.0"
続いてインストール。
C:\Users\m-namiki>bundle install Using diff-lcs 1.2.5 Using highline 1.6.21 Using net-ssh 2.8.0 Using rspec-core 2.14.8 Using rspec-expectations 2.14.5 Using rspec-mocks 2.14.6 Using rspec 2.14.1 Using specinfra 1.0.1 Using serverspec 1.0.0 Using bundler 1.6.0 Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
無事インストールされたので、Railsチュートリアル環境のディレクトリで初期設定を行います。
C:\Users\m-namiki>cd vagrant\rails3-tutorial C:\Users\m-namiki\vagrant\rails3-tutorial>serverspec-init Select OS type: 1) UN*X 2) Windows Select number: 1 Select a backend type: 1) SSH 2) Exec (local) Select number: 1 Vagrant instance y/n: y Auto-configure Vagrant from Vagrantfile? y/n: y + spec/ + spec/default/ + spec/default/httpd_spec.rb + spec/spec_helper.rb + Rakefile
テストコードを書く
Rakefileを見るとspec/以下にある*_spec.rbを実行対象とするようです。なので、デフォルトで作られるhttpd_spec.rbは削除して、新たにbase_spec.rbを書きます。
require 'spec_helper' describe yumrepo('epel') do it { should exist } it { should be_enabled } end describe yumrepo('remi') do it { should exist } it { should be_enabled } end
yumリポジトリにepelとremiが存在するかどうかのテストケースを作成してみました。上記でyumrepoと書いてある部分をResourceTypeといい、他にpackageとかserviceとか色々あるようです。詳細はserverspec - Resource Typesに記載されているので、後々確認してみます。
テスト実行
テストケースが完成したのでさっそく実行。
C:\Users\m-namiki\vagrant\rails3-tutorial>rake spec C:/Ruby193/bin/ruby.exe -S rspec spec/default/base_spec.rb Unable to find ~/.rspec because the HOME environment variable is not set FFFF Failures: 1) Yumrepo "epel" Failure/Error: Unable to find matching line from backtrace ArgumentError: non-absolute home non-absolute home (中略) Finished in 0.002 seconds 4 examples, 4 failures Failed examples: rspec ./spec/default/base_spec.rb:4 # Yumrepo "epel" rspec ./spec/default/base_spec.rb:5 # Yumrepo "epel" rspec ./spec/default/base_spec.rb:9 # Yumrepo "remi" rspec ./spec/default/base_spec.rb:10 # Yumrepo "remi" C:/Ruby193/bin/ruby.exe -S rspec spec/default/base_spec.rb failed
見事に失敗。メッセージを読むと環境変数HOMEがないから.rspecが見つからないよと言われてるようです。なので確認してみます。
C:\Users\m-namiki\vagrant\rails3-tutorial>set HOME HOME=%USERPROFILE% HOMEDRIVE=C: HOMEPATH=\Users\m-namiki C:\Users\m-namiki\vagrant\rails3-tutorial>set USERPROFILE USERPROFILE=C:\Users\m-namiki
環境変数HOMEは設定されていますが、Windows的な何かじゃないのかもしれない。。。なのでRakefileに定義してみました。
require 'rake' require 'rspec/core/rake_task' # ここにHOMEを追記 ENV['HOME'] = 'C:\Users\m-namiki' RSpec::Core::RakeTask.new(:spec) do |t| t.pattern = 'spec/*/*_spec.rb' end task :default => :spec
で、改めて実行してみると
C:\Users\m-namiki\vagrant\rails3-tutorial>rake spec C:/Ruby193/bin/ruby.exe -S rspec spec/default/base_spec.rb .... Finished in 25.05 seconds 4 examples, 0 failures
今度は無事に成功しました。まだ簡単なテストしか書いていないので次はもうちょっと色々なケースを追加してみようと思います。
参考にさせて頂いたページ
heroku toolbeltのインストールでハマった話
Ruby on Rails チュートリアル:実例を使って Rails を学ぼうの1.4節でHerokuにデプロイするというのがありますが、色々ハマったのでメモしておきます。
CentOS6.5でHeroku Toolbeltからtoolbetをダウンロードする場合、Standaloneを選択して下に表示されたwget -qO- https://toolbelt.heroku.com/install.sh | sh
を実行すれば良いはず。なので、まずはその通りにやってみました。
[vagrant@localhost ~]$ wget -qO- https://toolbelt.heroku.com/install.sh | sh [vagrant@localhost ~]$ heroku login -bash: heroku: command not found
が、インストールされていない。。。ので、「CentOSにheroku toolbeltをインストール」が失敗する場合の対処を参考に、証明書を無視する形で実行してみました。
[vagrant@localhost ~]$ wget --no-check-certificate https://toolbelt.heroku.com/install.sh --2014-03-27 03:06:26-- https://toolbelt.heroku.com/install.sh Resolving toolbelt.heroku.com... 23.21.54.126, 23.23.227.87, 50.19.233.212 Connecting to toolbelt.heroku.com|23.21.54.126|:443... connected. WARNING: certificate common name www.heroku.comtoolbelt.heroku.cominstall.shinstall.sh [vagrant@localhost ~]$ sudo sh ./install.sh This script requires superuser access to install software. You will be prompted for your password by sudo. Add the Heroku CLI to your PATH using: $ echo 'PATH="/usr/local/heroku/bin:$PATH"' >> ~/.profile Installation complete [vagrant@localhost ~]$ echo 'PATH="/usr/local/heroku/bin:$PATH"' >> .bashrc [vagrant@localhost ~]$ cat .bashrc # .bashrc # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi # User specific aliases and functions PATH="/usr/local/heroku/bin:$PATH" [vagrant@localhost ~]$ source .bashrc
で、実行してみると
[vagrant@localhost ~]$ heroku version /opt/rbenv/versions/1.9.3-p545/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- heroku-api (LoadError) from /opt/rbenv/versions/1.9.3-p545/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require' from /usr/local/heroku/lib/heroku/client/organizations.rb:1:in `<top (required)>' from /opt/rbenv/versions/1.9.3-p545/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require' from /opt/rbenv/versions/1.9.3-p545/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require' from /usr/local/heroku/lib/heroku/command/base.rb:4:in `<top (required)>' from /opt/rbenv/versions/1.9.3-p545/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require' from /opt/rbenv/versions/1.9.3-p545/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require' from /usr/local/heroku/lib/heroku/command/auth.rb:1:in `<top (required)>' from /opt/rbenv/versions/1.9.3-p545/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require' from /opt/rbenv/versions/1.9.3-p545/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require' from /usr/local/heroku/lib/heroku/command.rb:14:in `block in load' from /usr/local/heroku/lib/heroku/command.rb:13:in `each' from /usr/local/heroku/lib/heroku/command.rb:13:in `load' from /usr/local/heroku/lib/heroku/cli.rb:27:in `start' from /usr/local/heroku/bin/heroku:24:in `<main>'
heroku-apiというのが足りないらしい。これまた調べてみるとgemで提供されているようなのでGemfileを作ってbundlerでインストールしておきます。
[vagrant@localhost ~]$ cat Gemfile source 'https://rubygems.org' gem "heroku-api", "0.3.18" [vagrant@localhost ~]$ bundle install Fetching gem metadata from https://rubygems.org/... Resolving dependencies... Installing excon (0.32.1) Using multi_json (1.9.2) Installing heroku-api (0.3.18) Using bundler (1.5.3) Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
で、確認。
[vagrant@localhost ~]$ heroku version heroku-toolbelt/3.6.0 (x86_64-linux) ruby/1.9.3
今度は無事に実行できるようになりました。
データベース徹底攻略とWebアプリエンジニア養成読本
データベース徹底攻略 (WEB+DB PRESS plus)
- 作者: 松信嘉範,羽生章洋,ミック,奥野幹也,松下雅和,桑野章弘,青木峰郎,ひろせまさあき,小林篤,島田慶樹,WEB+DB PRESS編集部
- 出版社/メーカー: 技術評論社
- 発売日: 2014/03/15
- メディア: 大型本
- この商品を含むブログを見る
Webアプリエンジニア養成読本[しくみ、開発、環境構築・運用…全体像を最新知識で最初から! ] (Software Design plus)
- 作者: 和田裕介,石田絢一(uzulla),すがわらまさのり,斎藤祐一郎
- 出版社/メーカー: 技術評論社
- 発売日: 2014/03/11
- メディア: 大型本
- この商品を含むブログ (3件) を見る
Ruby on Railsチュートリアルの写経を始めました
Ruby on Rails チュートリアル:実例を使って Rails を学ぼう
Vagrant+Chefで環境構築する方法がなんとなく理解できてきましたが、ただ環境を作るだけじゃもったいないのでRailsチュートリアルの写経を始めてみようと思います。環境は以下の通りです。
OS | Windows7 x64 |
---|---|
VirtualBox | VirtualBox 4.3.8 for Windows hosts |
Ruby | ruby 1.9.3p484 (2013-11-22) [i386-mingw32] |
Vagrant | Vagrant 1.5.1 |
chef | chef (11.10.4 x86-mingw32) |
knife | knife-solo (0.4.1) |
berkshelf | berkshelf (2.0.14) |
VagrantとChefの導入についてはVagrant + Chefの導入 vol.1 - m-namikiの日記とVagrant + Chefの導入 vol.2 - m-namikiの日記で行ってますが、vagrant用のプラグインとberkshelfのインストールをしてなかったのでしておきます。
saharaのインストール
saharaは仮想サーバのスナップショットのようなものを作ることができるvagrant用プラグインです。環境のロールバック、コミットが可能なので何かあった場合に簡単に変更を取り消すことができます。インストール方法は以下の通りです。
vagrant plugin install sahara
vagrant-omnibusのインストール
vagrant-omnibusは仮想サーバ起動時にChefがインストールされているかどうかをチェックして、インストールされていない場合は自動でインストールしてくれるvagrant用プラグインです。環境構築を自動化したいのにそのために手動でChefをインストールするのは本末転倒なので非常にありがたいですね。インストール方法は以下の通りです。
vagrant plugin install vagrant-omnibus
Berkshelfのインストール
BerkshelfはChefのはcookbookの依存関係を管理するツール(らしい)です。まだhttp://community.opscode.com/からcookbookをダウンロードするのが楽になるくらいしか分かっていませんが、インストールしておきます。gemとして提供されているので以下の通りにインストールします。
gem install berkshelf --no-ri --no-rdoc
仮想サーバの作成
ここから仮想サーバの作成を行っていきます。
cd C:\Users\m-namiki\Documents\20_vagrant mkdir rails3_tutorial cd rails3_tutorial vagrant init chef/centos-6.5
chef-repoの作成
Vagrantfileがある場所にchef用のリポジトリを作成します。
knife solo init chef-repo cd chef-repo knife cookbook create ruby_env -o site-cookbooks
Berksfileの編集
Berkshelfがインストールしてあるとknife cookbook
時にBerksfileが作成されるので編集します。
// chef-repo/Berksfile site :opscode cookbook 'yum' cookbook 'ruby_build' cookbook 'rbenv' cookbook 'nodejs'
rubyのインストールはrbenv+ruby_buildで行います。nodejsについては、rails server
を実行したときにJavaScriptランタイムがインストールされていないと言われたのでインストールします。で、Berkshelfの実行。
berks install --path cookbooks
これでcookbooks/以下にyumやruby_build、rbenv、その他それらと依存関係があるcookbookがインストールされました。
site-cookbooks/ruby_env/recipes/default.rbの編集
続いてレシピの編集です。
# for install Ruby include_recipe "rbenv::default" include_recipe "rbenv::ruby_build" include_recipe "rbenv::rbenv_vars" service "iptables" do action [:disable, :stop] end log "done iptables stop." # add the EPEL repo yum_repository 'epel' do description 'Extra Packages for Enterprise Linux' mirrorlist 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-6&arch=$basearch' fastestmirror_enabled true gpgkey 'http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' action :create end # add the Remi repo yum_repository 'remi' do description 'Les RPM de Remi - Repository' baseurl 'http://rpms.famillecollet.com/enterprise/6/remi/x86_64/' gpgkey 'http://rpms.famillecollet.com/RPM-GPG-KEY-remi' fastestmirror_enabled true action :create end %w{sqlite-devel}.each do |p| package p do action :install end end log "done package install." rbenv_ruby "1.9.3-p545" do ruby_version "1.9.3-p545" global true end log "done ruby install." gem_package "rbenv-rehash" do action :install end log "done rehash install." gem_package "rails" do action :install version '3.2.14' end log "done rails3 install."
rbenvでrubyをインストールした場合、gem install
後に必ずrbenv rehash
をしなければならないそうなので、それを回避するためにrbenv-rehashを一緒にインストールしておきます。
Vagrantfileを編集
最後にVagrantfileを編集します。以下は変更部分です。
# Railsのサーバ用ポート config.vm.network "forwarded_port", guest: 3000, host: 3333 config.vm.network "private_network", ip: "192.168.33.10" config.vm.provider "virtualbox" do |vb| vb.customize ["modifyvm", :id, "--memory", "1024"] end config.vm.provision "chef_solo" do |chef| chef.cookbooks_path = ["./chef-repo/cookbooks", "./chef-repo/site-cookbooks"] chef.add_recipe "yum" chef.add_recipe "rbenv" chef.add_recipe "ruby_env" chef.add_recipe "nodejs" end # この行追加 config.omnibus.chef_version = :latest
forwarded_portについては、rails server
実行時にhttp://localhost:3000にアクセスしろと言われますが、そのままではアクセスできなかったので3333に変更しました。
起動
準備が整ったのでvagrant up
で起動します。自分の環境だとrubyとnodejsのインストールにそれぞれ10分くらい掛かりましたが、無事インストールが完了して起動しました。
[vagrant@localhost ~]$ ruby -v ruby 1.9.3p545 (2014-02-24 revision 45159) [x86_64-linux] [vagrant@localhost ~]$ rails -v Rails 3.2.14 [vagrant@localhost ~]$ node -v v0.10.15
で、ここまでの状態を一旦コミットしておきます。
vagrant sandbox on vagrant sandbox commit
これで何か変更を加えてもすぐに元に戻せるので安心です。
作成したVagrantfileやchef-repoを以下で公開してみました。
m-namiki/rails3-tutorial_environment · GitHub
写経したものはこっちに公開していきます。
m-namiki/rails3-projects · GitHub
実はこれをやってみたかった:)
GitHub実践入門
GitHub実践入門 ~Pull Requestによる開発の変革 (WEB+DB PRESS plus)
- 作者: 大塚弘記
- 出版社/メーカー: 技術評論社
- 発売日: 2014/03/20
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
Vagrant + Chefの導入 vol.2
入門Chef Solo - Infrastructure as Code
- 作者: 伊藤直也
- 出版社/メーカー: 伊藤直也
- 発売日: 2013/03/11
- メディア: Kindle版
- 購入: 16人 クリック: 1,027回
- この商品を含むブログ (17件) を見る
Rubyのインストール
ChefはRubyで動作するプログラムなので、Rubyをインストールしておく必要があります。Windows環境へのインストール方法はこちらを参照してください。バージョンについては、自分は1.9.3-p484を使っていますが、最新は1.9.3-p545なのでそちらの方が良いかと思います。
また、DevKitというものも必要となりますので、そちらもインストールしておきます。インストール方法はこちらを参照してください。
Chefのインストール
続いてはChefのインストールですが、まずは周辺プロダクトを整理してみます。
プロダクト名 | 概要 |
---|---|
chef-solo | chefに同梱されている単体で動作するプロビジョニングツール*1 |
knife-solo | chefのcookbookを作るためのツール |
Berkshelf | chefで使うcookbookを管理するgem |
Chefはクライアント・サーバによる集中管理方式でサーバの構成管理を行えますが、スタンドアロン方式も可能です。chef-soloはそのスタンドアロン方式用のツールです。次にknife-soloはknifeのプラグインでchef-soloで利用するレシピの雛形を作成したり、リモートでレシピを実行できるようにするためのサブコマンドが使えるようになります。Berkshelfはcookbookの依存関係を管理するツールらしいですが、ちょっとピンときません。ここは追々調べてみようと思います。
コマンドプロンプトで以下のコマンドを実行します。
gem install chef gem install knife-solo
cookbookの作成
インストールが完了したら、vagrant initしたディレクトリに移動してknife soloを実行します。前回の記事の例だとC:\Users\m-namiki\Documents\20_vagrant\10_sandboxになります。
cd C:\Users\m-namiki\Documents\20_vagrant\10_sandbox knife solo init chef-repo
実行が完了するとchef-repoというディレクトリが作成され、その下の階層は以下のようになります。
C:\Users\m-namiki\Documents\20_vagrant\10_sandbox>tree chef-repo C:\USERS\M-NAMIKI\DOCUMENTS\20_VAGRANT\10_SANDBOX\CHEF-REPO ├─.chef ├─cookbooks ├─data_bags ├─environments ├─nodes ├─roles └─site-cookbooks
次に簡単なレシピを書いてみます。chef-repoに移動して、knife cookbookを実行します。
cd chef-repo knife cookbook create sandbox -o site-cookbooks
実行が完了するとsite-cookbooks以下にsandboxというディレクトリが作成され、その中にも色々なディレクトリやファイルが作成されます。
C:\Users\m-namiki\Documents\20_vagrant\10_sandbox\chef-repo>tree site-cookbooks C:\USERS\M-NAMIKI\DOCUMENTS\20_VAGRANT\10_sandbox\CHEF-REPO\SITE-COOKBOOKS └─sandbox ├─attributes ├─definitions ├─files │ └─default ├─libraries ├─providers ├─recipes ├─resources └─templates └─default
recipes\default.rbというファイルがインストールするパッケージなどを記述するファイルです。まずは簡単にiptablesを停止・無効化するレシピを書いてみます。
# # Cookbook Name:: sandbox # Recipe:: default # # Copyright 2014, YOUR_COMPANY_NAME # # All rights reserved - Do Not Redistribute # service "iptables" do action [:disable, :stop] end log "done iptables stop."
レシピの書き方等については伊藤直也さん(@naoya)の入門Chef Solo - Infrastructure as Codeを筆頭に、ググればたくさん出てくるのでここでは割愛します。そしてようやく次は実行ですが、残念、m-namikiは力尽きてしまった!ので、続きはまた今度。
*1:サーバー構築・管理を自動化するツール