「Ubuntu14.04 Serverのインフラのテスト自動化(vagrant、serverspec、puppet)」|WEB+DB Press vol.80の特集記事から
はじめに
Rubyのための環境構築を行っているうちにInfrastructure as Codeへ軸が移ってきました。
構築した結果の確認をそろそろ自動化したいと考えているところで、WEB+DB Press vol.80で丁度良く特集が組まれたので、これを参考にしてserverspecの習得も始めました。
ただし、作業環境と対象環境は普段使用している環境で行いました。その結果、いくつかの違いが出たので、それをまとめました。
参考書籍
- 作者: 鶴長鎮一,宮下剛輔,縣俊貴,中村知成,西尾泰和,新井俊一,南川毅文,伊藤直也,石垣憲一,浅木朗,渡邊恵太,中島聡,はまちや2,竹原,川添貴生,河合宜文,WEB+DB PRESS編集部
- 出版社/メーカー: 技術評論社
- 発売日: 2014/04/24
- メディア: 大型本
- この商品を含むブログ (5件) を見る
概要
作業環境
Ubuntu14.04 Desktop 64bit
Ruby 1.9.3p484
serverspec 1.7.1
VirtualBox 4.3.12 r93733
Vagrant 1.6.3
※ Rubyはapt-getによりインストールした場合のバージョンです。
対象環境
Ubuntu14.04 Server 64bit
Puppet 3.6.1
手順
- serverspecのインストール
- 必要なディレクトリとファイルの作成
- テスト駆動インフラの実践(テスト失敗)
- プロビジョニング後、再テストの実施(テスト成功)
- テスト駆動インフラの繰り返し(Ubuntuでの結果に違いあり)
1.serverspecのインストール
serverspecはgemとして公開されているので、gem installでインストールします。
stupiddog@pc001:~$ sudo gem install serverspec --no-ri --no-rdoc Fetching: net-ssh-2.9.1.gem (100%) Fetching: rspec-core-2.14.8.gem (100%) Fetching: diff-lcs-1.2.5.gem (100%) Fetching: rspec-expectations-2.14.5.gem (100%) Fetching: rspec-mocks-2.14.6.gem (100%) Fetching: rspec-2.14.1.gem (100%) Fetching: highline-1.6.21.gem (100%) Fetching: specinfra-1.13.0.gem (100%) Fetching: serverspec-1.7.0.gem (100%) Successfully installed net-ssh-2.9.1 Successfully installed rspec-core-2.14.8 Successfully installed diff-lcs-1.2.5 Successfully installed rspec-expectations-2.14.5 Successfully installed rspec-mocks-2.14.6 Successfully installed rspec-2.14.1 Successfully installed highline-1.6.21 Successfully installed specinfra-1.13.0 Successfully installed serverspec-1.7.0 9 gems installed
※ rubyをユーザローカルとしてインストールしている場合は、sudoは不要です。
2.必要なディレクトリとファイルの作成
参考書籍の特集2第2章のP59を参考にして、ディレクトリとファイルを作成します。
テスト対象となるサーバーOSを、CentOS 6.4 から Ubuntu14.04 Server に変更してるため内容に違いがあります。
作成したディレクトリ
stupiddog@pc001:~/vm$ mkdir test-driven-infra stupiddog@pc001:~/vm$ cd test-driven-infra/ stupiddog@pc001:~/vm/test-driven-infra$ mkdir modules stupiddog@pc001:~/vm/test-driven-infra$ mkdir -p roles/app/manifests stupiddog@pc001:~/vm/test-driven-infra$ tree ~/vm/test-driven-infra/ /home/stupiddog/vm/test-driven-infra/ ├── modules └── roles └── app └── manifests 4 directories, 0 files
作成したファイル(環境構築部分)
- /roles/app/manifests/init.pp
class app {}
- provision.sh
#!/bin/sh role=$1 puppet apply --modulepath="/vagrant/modules:/vagrant/roles" -e "include $1"
- Vagrantfile
ベースとするBoxファイルと、最新リリースバージョンのpuppetをインストールするためのコードが特集とは異なります。
Boxファイルは、「Packerを利用したUbuntu14.04 ServerのVagrant用Boxファイルの作成」|ただいまRubyの修行中 - StupidDog's blogで作成したものを使用しています。
puppetのインストール方法については、公式サイトのInstalling Puppet: Debian and Ubuntu — Documentation — Puppet Labsを参考にしています。
# -*- mode: ruby -*- # vi: set ft=ruby : VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.box = "ubuntu1404" config.vm.box_url = "/home/stupiddog/boxs/ubuntu-14-04-x64-virtualbox.box" config.vm.provision :shell, inline: <<-EOF wget https://apt.puppetlabs.com/puppetlabs-release-$(lsb_release -cs).deb sudo dpkg -i puppetlabs-release-$(lsb_release -cs).deb sudo apt-get update sudo apt-get -y puppet EOF config.vm.define :app do |c| c.vm.provision :shell do |shell| shell.path = "provision.sh" shell.args = "app" end end end
作成したファイル(テスト部分)
serverspec-initコマンドにより、ひな型を生成してサンプル用の不要なファイルを削除します。
stupiddog@pc001:~/vm/test-driven-infra$ 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/app/ + spec/app/httpd_spec.rb + spec/spec_helper.rb + Rakefile stupiddog@pc001:~/vm/test-driven-infra$ rm spec/app/httpd_spec.rb
ここまでのディレクトリとファイル
stupiddog@pc001:~/vm/test-driven-infra$ tree ~/vm/test-driven-infra/ /home/stupiddog/vm/test-driven-infra/ ├── Rakefile ├── Vagrantfile ├── modules ├── provision.sh ├── roles │ └── app │ └── manifests │ └── init.pp └── spec ├── app └── spec_helper.rb 6 directories, 5 files
テスト用VMを起動
stupiddog@pc001:~/vm/test-driven-infra$ vagrant up
[実行ログの続き...]
stupiddog@pc001:~/vm/test-driven-infra$ vagrant up Bringing machine 'app' up with 'virtualbox' provider... ==> app: Importing base box 'ubuntu1404'... ==> app: Matching MAC address for NAT networking... ==> app: Setting the name of the VM: test-driven-infra_app_1401237349890_15840 ==> app: Clearing any previously set network interfaces... ==> app: Preparing network interfaces based on configuration... app: Adapter 1: nat ==> app: Forwarding ports... app: 22 => 2222 (adapter 1) ==> app: Booting VM... ==> app: Waiting for machine to boot. This may take a few minutes... app: SSH address: 127.0.0.1:2222 app: SSH username: vagrant app: SSH auth method: private key app: Warning: Connection timeout. Retrying... ==> app: Machine booted and ready! ==> app: Checking for guest additions in VM... ==> app: Mounting shared folders... app: /vagrant => /home/stupiddog/vm/test-driven-infra ==> app: Running provisioner: shell... app: Running: inline script ==> app: stdin: is not a tty ==> app: Selecting previously unselected package puppetlabs-release. ==> app: (Reading database ... 59020 files and directories currently installed.) ==> app: Preparing to unpack puppetlabs-release-trusty.deb ... ==> app: Unpacking puppetlabs-release (1.0-1) ... ==> app: Setting up puppetlabs-release (1.0-1) ... ==> app: Reading package lists... ==> app: Building dependency tree... ==> app: Reading state information... ==> app: The following extra packages will be installed: ==> app: augeas-lenses debconf-utils facter hiera libaugeas-ruby libaugeas0 ==> app: libruby1.9.1 libyaml-0-2 puppet-common ruby ruby-augeas ruby-json ruby-rgen ==> app: ruby-shadow ruby1.9.1 virt-what ==> app: Suggested packages: ==> app: augeas-doc augeas-tools puppet-el vim-puppet ruby-selinux libselinux-ruby1.8 ==> app: librrd-ruby1.9.1 librrd-ruby1.8 ri ruby-dev ruby1.9.1-examples ri1.9.1 ==> app: graphviz ruby1.9.1-dev ruby-switch ==> app: Recommended packages: ==> app: rdoc ==> app: The following NEW packages will be installed: ==> app: augeas-lenses debconf-utils facter hiera libaugeas-ruby libaugeas0 ==> app: libruby1.9.1 libyaml-0-2 puppet puppet-common ruby ruby-augeas ruby-json ==> app: ruby-rgen ruby-shadow ruby1.9.1 virt-what ==> app: 0 upgraded, 17 newly installed, 0 to remove and 12 not upgraded. ==> app: Need to get 4,438 kB of archives. ==> app: After this operation, 21.9 MB of additional disk space will be used. ==> app: Get:1 http://apt.puppetlabs.com/ trusty/main facter amd64 2.0.1-1puppetlabs1 [62.6 kB] ==> app: Get:2 http://us.archive.ubuntu.com/ubuntu/ trusty/main libyaml-0-2 amd64 0.1.4-3ubuntu3 [48.2 kB] ==> app: Get:3 http://apt.puppetlabs.com/ trusty/main hiera all 1.3.3-1puppetlabs1 [12.0 kB] ==> app: Get:4 http://apt.puppetlabs.com/ trusty/main puppet-common all 3.6.1-1puppetlabs1 [1,015 kB] ==> app: Get:5 http://us.archive.ubuntu.com/ubuntu/ trusty/main augeas-lenses all 1.2.0-0ubuntu1 [229 kB] ==> app: Get:6 http://apt.puppetlabs.com/ trusty/main puppet all 3.6.1-1puppetlabs1 [9,322 B] ==> app: Get:7 http://us.archive.ubuntu.com/ubuntu/ trusty/main debconf-utils all 1.5.51ubuntu2 [57.4 kB] ==> app: Get:8 http://us.archive.ubuntu.com/ubuntu/ trusty/main libruby1.9.1 amd64 1.9.3.484-2ubuntu1 [2,667 kB] ==> app: Get:9 http://us.archive.ubuntu.com/ubuntu/ trusty/main ruby1.9.1 amd64 1.9.3.484-2ubuntu1 [35.6 kB] ==> app: Get:10 http://us.archive.ubuntu.com/ubuntu/ trusty/main ruby all 1:1.9.3.4 [5,334 B] ==> app: Get:11 http://us.archive.ubuntu.com/ubuntu/ trusty/universe virt-what amd64 1.13-1 [13.6 kB] ==> app: Get:12 http://us.archive.ubuntu.com/ubuntu/ trusty/main libaugeas0 amd64 1.2.0-0ubuntu1 [140 kB] ==> app: Get:13 http://us.archive.ubuntu.com/ubuntu/ trusty/main ruby-augeas amd64 0.5.0-2 [13.2 kB] ==> app: Get:14 http://us.archive.ubuntu.com/ubuntu/ trusty/universe libaugeas-ruby all 0.5.0-2 [1,394 B] ==> app: Get:15 http://us.archive.ubuntu.com/ubuntu/ trusty/main ruby-shadow amd64 2.2.0-1 [11.2 kB] ==> app: Get:16 http://us.archive.ubuntu.com/ubuntu/ trusty/main ruby-json amd64 1.8.0-1build1 [49.0 kB] ==> app: Get:17 http://us.archive.ubuntu.com/ubuntu/ trusty/main ruby-rgen all 0.6.6-1 [68.7 kB] ==> app: dpkg-preconfigure: unable to re-open stdin: No such file or directory ==> app: Fetched 4,438 kB in 4min 4s (18.2 kB/s) ==> app: Selecting previously unselected package libyaml-0-2:amd64. ==> app: (Reading database ... 59026 files and directories currently installed.) ==> app: Preparing to unpack .../libyaml-0-2_0.1.4-3ubuntu3_amd64.deb ... ==> app: Unpacking libyaml-0-2:amd64 (0.1.4-3ubuntu3) ... ==> app: Selecting previously unselected package augeas-lenses. ==> app: Preparing to unpack .../augeas-lenses_1.2.0-0ubuntu1_all.deb ... ==> app: Unpacking augeas-lenses (1.2.0-0ubuntu1) ... ==> app: Selecting previously unselected package debconf-utils. ==> app: Preparing to unpack .../debconf-utils_1.5.51ubuntu2_all.deb ... ==> app: Unpacking debconf-utils (1.5.51ubuntu2) ... ==> app: Selecting previously unselected package libruby1.9.1. ==> app: Preparing to unpack .../libruby1.9.1_1.9.3.484-2ubuntu1_amd64.deb ... ==> app: Unpacking libruby1.9.1 (1.9.3.484-2ubuntu1) ... ==> app: Selecting previously unselected package ruby1.9.1. ==> app: Preparing to unpack .../ruby1.9.1_1.9.3.484-2ubuntu1_amd64.deb ... ==> app: Unpacking ruby1.9.1 (1.9.3.484-2ubuntu1) ... ==> app: Selecting previously unselected package ruby. ==> app: Preparing to unpack .../ruby_1%3a1.9.3.4_all.deb ... ==> app: Unpacking ruby (1:1.9.3.4) ... ==> app: Selecting previously unselected package virt-what. ==> app: Preparing to unpack .../virt-what_1.13-1_amd64.deb ... ==> app: Unpacking virt-what (1.13-1) ... ==> app: Selecting previously unselected package facter. ==> app: Preparing to unpack .../facter_2.0.1-1puppetlabs1_amd64.deb ... ==> app: Unpacking facter (2.0.1-1puppetlabs1) ... ==> app: Selecting previously unselected package libaugeas0. ==> app: Preparing to unpack .../libaugeas0_1.2.0-0ubuntu1_amd64.deb ... ==> app: Unpacking libaugeas0 (1.2.0-0ubuntu1) ... ==> app: Selecting previously unselected package ruby-augeas. ==> app: Preparing to unpack .../ruby-augeas_0.5.0-2_amd64.deb ... ==> app: Unpacking ruby-augeas (0.5.0-2) ... ==> app: Selecting previously unselected package libaugeas-ruby. ==> app: Preparing to unpack .../libaugeas-ruby_0.5.0-2_all.deb ... ==> app: Unpacking libaugeas-ruby (0.5.0-2) ... ==> app: Selecting previously unselected package ruby-shadow. ==> app: Preparing to unpack .../ruby-shadow_2.2.0-1_amd64.deb ... ==> app: Unpacking ruby-shadow (2.2.0-1) ... ==> app: Selecting previously unselected package ruby-json. ==> app: Preparing to unpack .../ruby-json_1.8.0-1build1_amd64.deb ... ==> app: Unpacking ruby-json (1.8.0-1build1) ... ==> app: Selecting previously unselected package hiera. ==> app: Preparing to unpack .../hiera_1.3.3-1puppetlabs1_all.deb ... ==> app: Unpacking hiera (1.3.3-1puppetlabs1) ... ==> app: Selecting previously unselected package ruby-rgen. ==> app: Preparing to unpack .../ruby-rgen_0.6.6-1_all.deb ... ==> app: Unpacking ruby-rgen (0.6.6-1) ... ==> app: Selecting previously unselected package puppet-common. ==> app: Preparing to unpack .../puppet-common_3.6.1-1puppetlabs1_all.deb ... ==> app: Unpacking puppet-common (3.6.1-1puppetlabs1) ... ==> app: Selecting previously unselected package puppet. ==> app: Preparing to unpack .../puppet_3.6.1-1puppetlabs1_all.deb ... ==> app: Unpacking puppet (3.6.1-1puppetlabs1) ... ==> app: Processing triggers for man-db (2.6.7.1-1) ... ==> app: Processing triggers for ureadahead (0.100.0-16) ... ==> app: ureadahead will be reprofiled on next reboot ==> app: Setting up libyaml-0-2:amd64 (0.1.4-3ubuntu3) ... ==> app: Setting up augeas-lenses (1.2.0-0ubuntu1) ... ==> app: Setting up debconf-utils (1.5.51ubuntu2) ... ==> app: Setting up virt-what (1.13-1) ... ==> app: Setting up libaugeas0 (1.2.0-0ubuntu1) ... ==> app: Setting up ruby (1:1.9.3.4) ... ==> app: Setting up facter (2.0.1-1puppetlabs1) ... ==> app: Setting up ruby-rgen (0.6.6-1) ... ==> app: Setting up ruby1.9.1 (1.9.3.484-2ubuntu1) ... ==> app: Setting up libruby1.9.1 (1.9.3.484-2ubuntu1) ... ==> app: Setting up ruby-augeas (0.5.0-2) ... ==> app: Setting up libaugeas-ruby (0.5.0-2) ... ==> app: Setting up ruby-shadow (2.2.0-1) ... ==> app: Setting up ruby-json (1.8.0-1build1) ... ==> app: Setting up hiera (1.3.3-1puppetlabs1) ... ==> app: Setting up puppet-common (3.6.1-1puppetlabs1) ... ==> app: Setting up puppet (3.6.1-1puppetlabs1) ... ==> app: * Starting puppet agent ==> app: puppet not configured to start, please edit /etc/default/puppet to enable ==> app: ...done. ==> app: Processing triggers for libc-bin (2.19-0ubuntu6) ... ==> app: Processing triggers for ureadahead (0.100.0-16) ... ==> app: Running provisioner: shell... app: Running: /tmp/vagrant-shell20140528-15607-1gkjyx1.sh ==> app: stdin: is not a tty ==> app: Warning: Setting templatedir is deprecated. See http://links.puppetlabs.com/env-settings-deprecations ==> app: (at /usr/lib/ruby/vendor_ruby/puppet/settings.rb:1071:in `each') ==> app: Notice: Compiled catalog for ubuntu-1404.vagrantup.com in environment production in 0.02 seconds ==> app: Notice: Finished catalog run in 0.01 seconds
※ 短時間でsudo apt-get updateを繰り返し過ぎるとリポジトリへのアクセスが遅くなるような…気のせいかな。
3.テスト駆動インフラの実践(テスト失敗)
テスト結果を見やすくするための設定ファイルも作成します。
テストコードの作成
- spec/app/ntp_spec.rb
require 'spec_helper' describe package('ntp') do if { should be_installed } end
テストを実行
stupiddog@pc001:~/vm/test-driven-infra$ rake spec /usr/bin/ruby1.9.1 -S rspec spec/app/ntp_spec.rb Package "ntp" should be installed (FAILED - 1) Failures: 1) Package "ntp" should be installed Failure/Error: it { should be_installed } sudo dpkg-query -f '${Status}' -W ntp | grep -E '^(install|hold) ok installed$' expected Package "ntp" to be installed # ./spec/app/ntp_spec.rb:4:in `block (2 levels) in <top (required)>' Finished in 3.9 seconds 1 example, 1 failure Failed examples: rspec ./spec/app/ntp_spec.rb:4 # Package "ntp" should be installed /usr/bin/ruby1.9.1 -S rspec spec/app/ntp_spec.rb failed
テストの失敗を確認。チェックに使用しているコマンドも表示されています。
4.プロビジョニング後、再テストの実施(テスト成功)
Puppetマニフェストの作成(ntpモジュール)
- module/ntp/manifests/init.pp
class ntp { package { 'ntp': ensure => installed } }
appロールへのモジュール呼び出し追加
class app { include ntp }
Puppetマニフェストの適用
stupiddog@pc001:~/vm/test-driven-infra$ vagrant provision ==> app: Running provisioner: shell... app: Running: inline script ==> app: stdin: is not a tty ==> app: (Reading database ... 62069 files and directories currently installed.) ==> app: Preparing to unpack puppetlabs-release-trusty.deb ... ==> app: Unpacking puppetlabs-release (1.0-1) over (1.0-1) ... ==> app: Setting up puppetlabs-release (1.0-1) ... ==> app: Reading package lists... ==> app: Building dependency tree... ==> app: Reading state information... ==> app: puppet is already the newest version. ==> app: 0 upgraded, 0 newly installed, 0 to remove and 22 not upgraded. ==> app: Running provisioner: shell... app: Running: /tmp/vagrant-shell20140609-5527-7v3h9v.sh ==> app: stdin: is not a tty ==> app: Warning: Setting templatedir is deprecated. See http://links.puppetlabs.com/env-settings-deprecations ==> app: (at /usr/lib/ruby/vendor_ruby/puppet/settings.rb:1071:in `each') ==> app: Notice: Compiled catalog for ubuntu-1404.vagrantup.com in environment production in 0.19 seconds ==> app: Notice: /Stage[main]/Ntp/Package[ntp]/ensure: ensure changed 'purged' to 'present' ==> app: Notice: Finished catalog run in 12.68 seconds
テストの実行
stupiddog@pc001:~/vm/test-driven-infra$ rake spec /usr/bin/ruby1.9.1 -S rspec spec/app/ntp_spec.rb Package "ntp" should be installed Finished in 3.96 seconds 1 example, 0 failures
テストの成功を確認。これで、テスト駆動インフラの入り口に着ました。
5.テスト駆動インフラの繰り返し(Ubuntuでの結果に違いあり)
テストの追加
ntpdサービスが自動起動するようになっている(be_enabled)と、起動している(be_running)をテストするコードを追加する。
- spec/app/ntp_spec.rb
require 'spec_helper' describe package('ntp') do it { should be_installed } end describe service('ntpd') do it { should be_enabled } it { should be_running } end
テストの実施(テスト失敗)
stupiddog@pc001:~/vm/test-driven-infra$ rake spec /usr/bin/ruby1.9.1 -S rspec spec/app/ntp_spec.rb Package "ntp" should be installed Service "ntpd" should be enabled (FAILED - 1) should be running Failures: 1) Service "ntpd" should be enabled Failure/Error: it { should be_enabled } sudo ls /etc/rc3.d/ | grep -- '^S..ntpd' || sudo grep 'start on' /etc/init/ntpd.conf expected Service "ntpd" to be enabled # ./spec/app/ntp_spec.rb:8:in `block (2 levels) in <top (required)>' Finished in 4.06 seconds 3 examples, 1 failure Failed examples: rspec ./spec/app/ntp_spec.rb:8 # Service "ntpd" should be enabled /usr/bin/ruby1.9.1 -S rspec spec/app/ntp_spec.rb failed
新しく追加したテストの失敗を確認。
ここで、テスト結果を見ると書籍と異なることが分かります。
失敗しているのは、「ntpdサービスが自動起動するようになっている(be_enabled)」のみで、「起動している(be_running)」は成功しています。
これは、Ubuntuのaptでntpをインストールした場合、自動起動の設定も合わせて行われるためです。
念のためテスト対象の仮想環境でntpサービスが起動していることを確認します。
stupiddog@pc001:~/vm/test-driven-infra$ vagrant ssh Welcome to Ubuntu 14.04 LTS (GNU/Linux 3.13.0-24-generic x86_64) * Documentation: https://help.ubuntu.com/ Last login: Mon May 19 10:27:04 2014 from 10.0.2.2 vagrant@ubuntu-1404:~$ ps aux | grep ntpd | grep -v grep ntp 2026 0.0 0.2 31444 2056 ? Ss 07:11 0:00 /usr/sbin/ntpd -p /var/run/ntpd.pid -g -u 105:113 vagrant@ubuntu-1404:~$
ntpサービス(ntpd)が起動しています。
では何故「ntpdサービスが自動起動するようになっている(be_enabled)」が失敗となったのか。
もう一度、テスト結果を確認すると失敗しているテストのコマンドが出力されていることが分かります。
1) Service "ntpd" should be enabled Failure/Error: it { should be_enabled } sudo ls /etc/rc3.d/ | grep -- '^S..ntpd' || sudo grep 'start on' /etc/init/ntpd.conf expected Service "ntpd" to be enabled # ./spec/app/ntp_spec.rb:8:in `block (2 levels) in <top (required)>'
二種類のコマンドのどちらかが成功した場合にテスト成功となるようです。
まず、コマンドを手入力してみます。
vagrant@ubuntu-1404:~$ sudo ls /etc/rc3.d/ | grep -- '^S..ntpd' vagrant@ubuntu-1404:~$ sudo ls /etc/rc3.d/ README S20rsync S20virtualbox-guest-utils S21puppet S23ntp S70dns-clean S70pppd-dns S99grub-common S99ondemand S99rc.local vagrant@ubuntu-1404:~$ sudo grep 'start on' /etc/init/ntpd.conf grep: /etc/init/ntpd.conf: No such file or directory
結果から、/etc/init/ntpd.confファイルは存在しないようです。
そこでもう一つのコマンドを確認すると、起動スクリプトの有無をチェックしていることが分かります。
しかし、実際に存在しているntpの起動スクリプト名が「S23ntpd」ではなく「S23ntp」なので条件に一致しません。
結果の考察と対応
serverspecでのテストで、成功となるケースが失敗となってしまいました。
ntpサービスがファイル配置や名前を頻繁に変えてしまうのが原因だと思います。
これで、serverspecを使用しない~ではなく、OSSでありインフラテストの仕組みを提供しているのだから自分の環境で正しいテストが出来るようにテストコードを書き直します。
どうやってコマンドが生成されているか
テストが失敗した場合に、テストに使用しているコマンドが出力されるので敢えて存在しないサービス名を指定してみました。
- spec/app/ntp_spec.rb
stupiddog@pc001:~/vm/test-driven-infra$ cat spec/app/ntp_spec.rb require 'spec_helper' describe package('ntp') do it { should be_installed } end describe service('aaa') do it { should be_enabled } it { should be_running } end stupiddog@pc001:~/vm/test-driven-infra$ rake spec /usr/bin/ruby1.9.1 -S rspec spec/app/ntp_spec.rb Package "ntp" should be installed Service "aaa" should be enabled (FAILED - 1) should be running (FAILED - 2) Failures: 1) Service "aaa" should be enabled Failure/Error: it { should be_enabled } sudo ls /etc/rc3.d/ | grep -- '^S..aaa' || sudo grep 'start on' /etc/init/aaa.conf expected Service "aaa" to be enabled # ./spec/app/ntp_spec.rb:8:in `block (2 levels) in <top (required)>' 2) Service "aaa" should be running Failure/Error: it { should be_running } sudo ps aux | grep -w -- aaa | grep -qv grep expected Service "aaa" to be running # ./spec/app/ntp_spec.rb:9:in `block (2 levels) in <top (required)>' Finished in 4.02 seconds 3 examples, 2 failures Failed examples: rspec ./spec/app/ntp_spec.rb:8 # Service "aaa" should be enabled rspec ./spec/app/ntp_spec.rb:9 # Service "aaa" should be running /usr/bin/ruby1.9.1 -S rspec spec/app/ntp_spec.rb failed
describe service()に指定した名前が、そのまま使用されるようです。
そこで、テストコードを次のように書き直してテストが正常に行われるようにしました。
- spec/app/ntp_spec.rb
require 'spec_helper' describe package('ntp') do it { should be_installed } end describe service('ntp') do it { should be_enabled } end describe service('ntpd') do it { should be_running } end
テストの実施
stupiddog@pc001:~/vm/test-driven-infra$ rake spec /usr/bin/ruby1.9.1 -S rspec spec/app/ntp_spec.rb Package "ntp" should be installed Service "ntp" should be enabled Service "ntpd" should be running Finished in 4.02 seconds 3 examples, 0 failures
これで対象環境のテストコードと、ntpサービスを導入したUbuntu14.04 Server環境を作るためのコードが作成できました。
まとめ
今回、テストコードを変更してテストを通す結果となりました。
テストが成功するようにテストコードを変更したことになりますが、手本とした書籍のコードがたまたま存在していただけです。
ゼロから構築することを考えた場合、serverspecでの記述方法だけでなく、どうやってチェックしているかを知らないと新しい要素のテストコードを記述できないことが分かりました。
実施してみて注意することが分かったので、今後は他の条件のテストも行って習得度を上げていきます。