Serverspecとは何か? †
サーバーの設定をしていこう †
$ cd ~/Documents/MyVagrant $ mkdir serverspec_lessons $ cd serverspec_lessons $ vagrant init bento/centos-6.7
$ vi Vagrantfile config.vm.box = "bento/centos-6.7"
config.vm.define "host" do |node|
node.vm.box = "bento/centos-6.7"
node.vm.hostname = "host"
node.vm.network :private_network, ip: "192.168.33.10"
end
config.vm.define "web" do |node|
node.vm.box = "bento/centos-6.7"
node.vm.hostname = "web"
node.vm.network :private_network, ip: "192.168.33.11"
end
$ vagrant up
$ vagrant status Current machine states: host running (virtualbox) web running (virtualbox) This environment represents multiple VMs. The VMs are all listed above with their current state. For more information about a specific VM, run `vagrant status NAME`.
$ vagrant ssh host $ vi .ssh/config Host web HostName 192.168.33.11 $ chmod 600 .ssh/config
$ ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/home/vagrant/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again:
[vagrant@host ~]$ ssh-copy-id web The authenticity of host '192.168.33.11 (192.168.33.11)' can't be established. RSA key fingerprint is 90:d8:41:6f:c5:39:1d:54:0d:43:4e:34:dc:f1:d2:6b. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.33.11' (RSA) to the list of known hosts. vagrant@192.168.33.11's password:
$ ssh web $ exit Serverspecをインストールしよう †
$ sudo yum -y install git
$ git clone https://github.com/dotinstallres/centos65.git $ cd centos65 $ ./run.sh .... .... PLAY RECAP ********************************************************************* localhost : ok=32 changed=31 unreachable=0 failed=0
$ exec $SHELL -l
$ ruby -v ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
$ gem list *** LOCAL GEMS *** bigdecimal (1.2.6) io-console (0.4.3) json (1.8.1) minitest (5.4.3) power_assert (0.2.2) psych (2.0.8) rake (10.4.2) rdoc (4.2.0) test-unit (3.0.8)
$ gem install itamae serverspec
$ gem list *** LOCAL GEMS *** ansi (1.5.0) .... diff-lcs (1.3) hashie (3.5.5) .... itamae (1.9.11) .... multi_json (1.12.1) net-scp (1.2.1) net-ssh (4.1.0) net-telnet (0.1.1) .... rspec (3.5.0) rspec-core (3.5.4) rspec-expectations (3.5.0) rspec-its (1.2.0) rspec-mocks (3.5.0) rspec-support (3.5.0) schash (0.1.2) serverspec (2.38.0) sfl (2.3) specinfra (2.67.2) .... thor (0.19.4) $ cd serverspec-initを使ってみよう †
$ mkdir myproject $ cd myproject/ $ mkdir cookbooks $ cd cookbooks/ $ vi recipe.rb $ cd ..
$ pwd /home/vagrant/myproject $ 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: n Input target host name: web + spec/ + spec/web/ + spec/web/sample_spec.rb + spec/spec_helper.rb + Rakefile + .rspec
/home/vagrant/myproject |--.rspec |--Rakefile |--cookbooks | |--recipe.rb |--spec | |--spec_helper.rb | |--web | | |--sample_spec.rb
$ rm spec/web/sample_spec.rb $ vi spec/web/httpd_spec.rb はじめてのテストをしてみよう †
# 1. fail
# 2. pass
# 3. refactor
require 'spec_helper'
describe package('httpd') do
it { should be_installed }
end
$ rake spec
/home/vagrant/.rbenv/....
Package "httpd"
should be installed (FAILED - 1)
Failures:
1) Package "httpd" should be installed
On host `web'
Failure/Error: it { should be_installed }
expected Package "httpd" to be installed
sudo -p 'Password: ' /bin/sh -c rpm\ -q\ httpd
package httpd is not installed
# ./spec/web/httpd_spec.rb:8:in `block (2 levels) in <top (required)>'
Finished in 1.08 seconds (files took 0.5465 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/web/httpd_spec.rb:8 # Package "httpd" should be installed
/home/vagrant/.rbenv/.... failed
package 'httpd'
$ itamae ssh -h web cookbooks/recipe.rb -n
$ itamae ssh -h web cookbooks/recipe.rb INFO : Starting Itamae... INFO : Recipe: /home/vagrant/myproject/cookbooks/recipe.rb INFO : package[httpd] installed will change from 'false' to 'true'
$ rake spec /home/vagrant/.rbenv/.... Package "httpd" should be installed Finished in 0.64223 seconds (files took 0.43663 seconds to load) 1 example, 0 failures ResourceとMatcherを調べてみよう †
httpdのテストをしてみよう †
# 1. fail
# 2. pass
# 3. refactor
require 'spec_helper'
describe package('httpd') do
it { should be_installed }
end
describe service('httpd') do
it { should be_enabled }
it { should be_running }
end
describe port(80) do
it { should be_listening }
end
$ rake spec
/home/vagrant/.rbenv/....
....
Service "httpd"
should be enabled (FAILED - 1)
should be running (FAILED - 2)
Port "80"
should be listening (FAILED - 3)
Failures:
1) Service "httpd" should be enabled
On host `web'
Failure/Error: it { should be_enabled }
expected Service "httpd" to be enabled
sudo -p 'Password: ' /bin/sh -c chkconfig\ --list\ httpd\ \|\ grep\ 3:on
# ./spec/web/httpd_spec.rb:12:in `block (2 levels) in <top (required)>'
2) Service "httpd" should be running
On host `web'
Failure/Error: it { should be_running }
expected Service "httpd" to be running
sudo -p 'Password: ' /bin/sh -c service\ httpd\ status
httpd is stopped
# ./spec/web/httpd_spec.rb:13:in `block (2 levels) in <top (required)>'
3) Port "80" should be listening
On host `web'
Failure/Error: it { should be_listening }
expected Port "80" to be listening
sudo -p 'Password: ' /bin/sh -c netstat\ -tunl\ \|\ grep\ --\ :80\\\
# ./spec/web/httpd_spec.rb:17:in `block (2 levels) in <top (required)>'
Finished in 0.86085 seconds (files took 0.43814 seconds to load)
4 examples, 3 failures
Failed examples:
rspec ./spec/web/httpd_spec.rb:12 # Service "httpd" should be enabled
rspec ./spec/web/httpd_spec.rb:13 # Service "httpd" should be running
rspec ./spec/web/httpd_spec.rb:17 # Port "80" should be listening
/home/vagrant/.rbenv/.... failed
package 'httpd' service 'httpd' do action [:enable, :start] end
$ itamae ssh -h web cookbooks/recipe.rb INFO : Starting Itamae... INFO : Recipe: /home/vagrant/myproject/cookbooks/recipe.rb INFO : service[httpd] enabled will change from 'false' to 'true' INFO : service[httpd] running will change from 'false' to 'true'
$ rake spec /home/vagrant/.rbenv/.... .... Service "httpd" should be enabled should be running Port "80" should be listening Finished in 0.8126 seconds (files took 0.4321 seconds to load) 4 examples, 0 failures fileリソースを使ってみよう †
# 1. fail
# 2. pass
# 3. refactor
require 'spec_helper'
describe package('httpd') do
it { should be_installed }
end
describe service('httpd') do
it { should be_enabled }
it { should be_running }
end
describe port(80) do
it { should be_listening }
end
describe file('/var/www/html/index.html') do
it { should be_file }
it { should be_owned_by 'apache' }
it { should be_grouped_into 'apache' }
its(:content) { should match /Hello World/ }
end
$ rake spec
/home/vagrant/.rbenv/....
....
File "/var/www/html/index.html"
should be file (FAILED - 1)
should be owned by "apache" (FAILED - 2)
should be grouped into "apache" (FAILED - 3)
content
should match /Hello World/ (FAILED - 4)
Failures:
1) File "/var/www/html/index.html" should be file
On host `web'
Failure/Error: it { should be_file }
expected `File "/var/www/html/index.html".file?` to return true, got false
sudo -p 'Password: ' /bin/sh -c test\ -f\ /var/www/html/index.html
# ./spec/web/httpd_spec.rb:21:in `block (2 levels) in <top (required)>'
2) File "/var/www/html/index.html" should be owned by "apache"
On host `web'
Failure/Error: it { should be_owned_by 'apache' }
expected `File "/var/www/html/index.html".owned_by?("apache")` to return true, got false
sudo -p 'Password: ' /bin/sh -c stat\ -c\ \%U\ /var/www/html/index.html\ \|\ grep\ --\ \\\^apache\\\$
# ./spec/web/httpd_spec.rb:22:in `block (2 levels) in <top (required)>'
3) File "/var/www/html/index.html" should be grouped into "apache"
On host `web'
Failure/Error: it { should be_grouped_into 'apache' }
expected `File "/var/www/html/index.html".grouped_into?("apache")` to return true, got false
sudo -p 'Password: ' /bin/sh -c stat\ -c\ \%G\ /var/www/html/index.html\ \|\ grep\ --\ \\\^apache\\\$
# ./spec/web/httpd_spec.rb:23:in `block (2 levels) in <top (required)>'
4) File "/var/www/html/index.html" content should match /Hello World/
On host `web'
Failure/Error: its(:content) { should match /Hello World/ }
expected "" to match /Hello World/
Diff:
@@ -1,2 +1,2 @@
-/Hello World/
+""
sudo -p 'Password: ' /bin/sh -c cat\ /var/www/html/index.html\ 2\>\ /dev/null\ \|\|\ echo\ -n
# ./spec/web/httpd_spec.rb:24:in `block (2 levels) in <top (required)>'
Finished in 0.90728 seconds (files took 0.4069 seconds to load)
8 examples, 4 failures
Failed examples:
rspec ./spec/web/httpd_spec.rb:21 # File "/var/www/html/index.html" should be file
rspec ./spec/web/httpd_spec.rb:22 # File "/var/www/html/index.html" should be owned by "apache"
rspec ./spec/web/httpd_spec.rb:23 # File "/var/www/html/index.html" should be grouped into "apache"
rspec ./spec/web/httpd_spec.rb:24 # File "/var/www/html/index.html" content should match /Hello World/
/home/vagrant/.rbenv/.... failed
$ cd cookbooks/ $ mkdir files $ cd files/ $ vi index.html <html> Hello World </html> $ cd ../..
package 'httpd' service 'httpd' do action [:enable, :start] end remote_file '/var/www/html/index.html' do owner 'apache' group 'apache' end
$ itamae ssh -h web cookbooks/recipe.rb INFO : Starting Itamae... INFO : Recipe: /home/vagrant/myproject/cookbooks/recipe.rb INFO : remote_file[/var/www/html/index.html] exist will change from 'false' to 'true' INFO : remote_file[/var/www/html/index.html] modified will change from 'false' to 'true' INFO : remote_file[/var/www/html/index.html] owner will be 'apache' INFO : remote_file[/var/www/html/index.html] group will be 'apache' INFO : diff: INFO : --- /dev/null 2017-03-12 12:01:09.240000001 +0000 INFO : +++ /tmp/itamae_tmp/1489326611.9137843 2017-03-12 13:50:11.959835316 +0000 INFO : @@ -0,0 +1,3 @@ INFO : +<html> INFO : +Hello World INFO : +</html>
$ rake spec
/home/vagrant/.rbenv/....
....
File "/var/www/html/index.html"
should be file
should be owned by "apache"
should be grouped into "apache"
content
should match /Hello World/
Finished in 0.8986 seconds (files took 0.43226 seconds to load)
8 examples, 0 failures
PHPのテストをしてみよう †
$ vi spec/web/php_spec.rb require 'spec_helper'
%w(php php-devel php-mbstring php-gd).each do |pkg|
describe package(pkg) do
it { should be_installed }
end
end
$ rake spec
/home/vagrant/.rbenv/....
....
Package "php"
should be installed (FAILED - 1)
Package "php-devel"
should be installed (FAILED - 2)
Package "php-mbstring"
should be installed (FAILED - 3)
Package "php-gd"
should be installed (FAILED - 4)
Failures:
1) Package "php" should be installed
On host `web'
Failure/Error: it { should be_installed }
expected Package "php" to be installed
sudo -p 'Password: ' /bin/sh -c rpm\ -q\ php
package php is not installed
# ./spec/web/php_spec.rb:5:in `block (3 levels) in <top (required)>'
2) Package "php-devel" should be installed
On host `web'
Failure/Error: it { should be_installed }
expected Package "php-devel" to be installed
sudo -p 'Password: ' /bin/sh -c rpm\ -q\ php-devel
package php-devel is not installed
# ./spec/web/php_spec.rb:5:in `block (3 levels) in <top (required)>'
3) Package "php-mbstring" should be installed
On host `web'
Failure/Error: it { should be_installed }
expected Package "php-mbstring" to be installed
sudo -p 'Password: ' /bin/sh -c rpm\ -q\ php-mbstring
package php-mbstring is not installed
# ./spec/web/php_spec.rb:5:in `block (3 levels) in <top (required)>'
4) Package "php-gd" should be installed
On host `web'
Failure/Error: it { should be_installed }
expected Package "php-gd" to be installed
sudo -p 'Password: ' /bin/sh -c rpm\ -q\ php-gd
package php-gd is not installed
# ./spec/web/php_spec.rb:5:in `block (3 levels) in <top (required)>'
Finished in 1.12 seconds (files took 0.44041 seconds to load)
12 examples, 4 failures
Failed examples:
rspec ./spec/web/php_spec.rb[1:1] # Package "php" should be installed
rspec ./spec/web/php_spec.rb[2:1] # Package "php-devel" should be installed
rspec ./spec/web/php_spec.rb[3:1] # Package "php-mbstring" should be installed
rspec ./spec/web/php_spec.rb[4:1] # Package "php-gd" should be installed
/home/vagrant/.rbenv/.... failed
package 'httpd' service 'httpd' do action [:enable, :start] end remote_file '/var/www/html/index.html' do owner 'apache' group 'apache' end %w(php php-devel php-mbstring php-gd).each do |pkg| package pkg end
$ itamae ssh -h web cookbooks/recipe.rb INFO : Starting Itamae... INFO : Recipe: /home/vagrant/myproject/cookbooks/recipe.rb INFO : package[php] installed will change from 'false' to 'true' INFO : package[php-devel] installed will change from 'false' to 'true' INFO : package[php-mbstring] installed will change from 'false' to 'true' INFO : package[php-gd] installed will change from 'false' to 'true'
$ rake spec /home/vagrant/.rbenv/.... .... Package "php" should be installed Package "php-devel" should be installed Package "php-mbstring" should be installed Package "php-gd" should be installed Finished in 1.13 seconds (files took 0.42836 seconds to load) 12 examples, 0 failures php_configリソースを使ってみよう †
require 'spec_helper'
%w(php php-devel php-mbstring php-gd).each do |pkg|
describe package(pkg) do
it { should be_installed }
end
end
describe php_config('date.timezone') do
its(:value) { should eq 'Asia/Tokyo' }
end
$ rake spec
/home/vagrant/.rbenv/....
....
Php config "date.timezone"
value
should eq "Asia/Tokyo" (FAILED - 1)
Failures:
1) Php config "date.timezone" value should eq "Asia/Tokyo"
On host `web'
Failure/Error: its(:value) { should eq 'Asia/Tokyo' }
expected: "Asia/Tokyo"
got: ""
(compared using ==)
sudo -p 'Password: ' /bin/sh -c php\ \ -r\ \'echo\ get_cfg_var\(\ \"date.timezone\"\ \)\;\'
# ./spec/web/php_spec.rb:10:in `block (2 levels) in <top (required)>'
Finished in 1.18 seconds (files took 0.42907 seconds to load)
13 examples, 1 failure
Failed examples:
rspec ./spec/web/php_spec.rb:10 # Php config "date.timezone" value should eq "Asia/Tokyo"
/home/vagrant/.rbenv/.... failed
package 'httpd'
service 'httpd' do
action [:enable, :start]
end
remote_file '/var/www/html/index.html' do
owner 'apache'
group 'apache'
end
%w(php php-devel php-mbstring php-gd).each do |pkg|
package pkg
end
file '/etc/php.ini' do
action :edit
block do |content|
content.gsub!(';date.timezone =', 'date.timezone = Asia/Tokyo')
end
end
$ itamae ssh -h web cookbooks/recipe.rb INFO : Starting Itamae... INFO : Recipe: /home/vagrant/myproject/cookbooks/recipe.rb INFO : file[/etc/php.ini] modified will change from 'false' to 'true' INFO : diff: INFO : --- /etc/php.ini 2016-08-11 20:36:21.000000000 +0000 INFO : +++ /tmp/itamae_tmp/1489328313.8955498 2017-03-12 14:18:34.023193526 +0000 INFO : @@ -943,7 +943,7 @@ INFO : [Date] INFO : ; Defines the default timezone used by the date functions INFO : ; http://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone INFO : -;date.timezone = INFO : +date.timezone = Asia/Tokyo INFO : INFO : ; http://www.php.net/manual/en/datetime.configuration.php#ini.date.default-latitude INFO : ;date.default_latitude = 31.7667
$ rake spec
/home/vagrant/.rbenv/....
....
Php config "date.timezone"
value
should eq "Asia/Tokyo"
Finished in 1.15 seconds (files took 0.4326 seconds to load)
13 examples, 0 failures
commandリソースを使ってみよう †
require 'spec_helper'
# describe file('/home/vagrant/myapp') do
# it { should be_directory }
# end
describe command('ls -la /home/vagrant') do
its(:stdout) { should match /\smyapp$/ }
end
/home/vagrant/myproject |--.rspec |--Rakefile |--cookbooks | |--files | | |--index.html | |--recipe.rb |--spec | |--spec_helper.rb | |--web | | |--files_spec.rb | | |--httpd_spec.rb | | |--php_spec.rb
$ rake spec
/home/vagrant/.rbenv/....
Command "ls -la /home/vagrant"
stdout
should match /\smyapp$/ (FAILED - 1)
....
Failures:
1) Command "ls -la /home/vagrant" stdout should match /\smyapp$/
On host `web'
Failure/Error: its(:stdout) { should match /\smyapp$/ }
expected "total 32\ndrwx------. 3 vagrant vagrant 4096 Mar 12 12:05 .\ndrwxr-xr-x. 3 root root 4096 May ...ant root 4096 Mar 12 12:01 .ssh\n-rw-r--r--. 1 vagrant vagrant 6 May 21 2016 .vbox_version\n" to match /\smyapp$/
Diff:
@@ -1,2 +1,10 @@
-/\smyapp$/
+total 32
+drwx------. 3 vagrant vagrant 4096 Mar 12 12:05 .
+drwxr-xr-x. 3 root root 4096 May 21 2016 ..
+-rw-------. 1 vagrant vagrant 5 Mar 12 12:05 .bash_history
+-rw-r--r--. 1 vagrant vagrant 18 Jul 23 2015 .bash_logout
+-rw-r--r--. 1 vagrant vagrant 176 Jul 23 2015 .bash_profile
+-rw-r--r--. 1 vagrant vagrant 124 Jul 23 2015 .bashrc
+drwx------. 2 vagrant root 4096 Mar 12 12:01 .ssh
+-rw-r--r--. 1 vagrant vagrant 6 May 21 2016 .vbox_version
sudo -p 'Password: ' /bin/sh -c ls\ -la\ /home/vagrant
total 32
drwx------. 3 vagrant vagrant 4096 Mar 12 12:05 .
drwxr-xr-x. 3 root root 4096 May 21 2016 ..
-rw-------. 1 vagrant vagrant 5 Mar 12 12:05 .bash_history
-rw-r--r--. 1 vagrant vagrant 18 Jul 23 2015 .bash_logout
-rw-r--r--. 1 vagrant vagrant 176 Jul 23 2015 .bash_profile
-rw-r--r--. 1 vagrant vagrant 124 Jul 23 2015 .bashrc
drwx------. 2 vagrant root 4096 Mar 12 12:01 .ssh
-rw-r--r--. 1 vagrant vagrant 6 May 21 2016 .vbox_version
# ./spec/web/files_spec.rb:8:in `block (2 levels) in <top (required)>'
Finished in 1.15 seconds (files took 0.45466 seconds to load)
14 examples, 1 failure
Failed examples:
rspec ./spec/web/files_spec.rb:8 # Command "ls -la /home/vagrant" stdout should match /\smyapp$/
/home/vagrant/.rbenv/.... failed
package 'httpd'
service 'httpd' do
action [:enable, :start]
end
remote_file '/var/www/html/index.html' do
owner 'apache'
group 'apache'
end
%w(php php-devel php-mbstring php-gd).each do |pkg|
package pkg
end
file '/etc/php.ini' do
action :edit
block do |content|
content.gsub!(';date.timezone =', 'date.timezone = Asia/Tokyo')
end
end
directory '/home/vagrant/myapp'
$ itamae ssh -h web cookbooks/recipe.rb INFO : Starting Itamae... INFO : Recipe: /home/vagrant/myproject/cookbooks/recipe.rb INFO : directory[/home/vagrant/myapp] exist will change from 'false' to 'true'
$ rake spec
/home/vagrant/.rbenv/....
Command "ls -la /home/vagrant"
stdout
should match /\smyapp$/
....
Finished in 1.23 seconds (files took 0.42573 seconds to load)
14 examples, 0 failures
|