連載
» 2016年08月12日 05時00分 公開

実際に検証済み!OSS徹底比較(5)サーバテスト自動化【前編】:OSSのサーバテスト自動化ツール徹底検証 2016年版 〜Serverspec編〜 (6/8)

[森元敏雄,TIS]

ServerspecのTIPS

 Serverspecで、各アプリケーションの動作確認や設定の確認に使用するコマンドは、公式サイトのResource Typesで詳細に解説されている。以下では今回の検証に使用したコマンドの用法や注意点などを記述している。

1.パッケージのインストール有無

 パッケージのインストールの有無を確認するにはdescribe packageを使用する。以下の記述例は複数のパッケージをループ処理で確認するものとなっている。

 php/php-mysql insall check
%w{ php php-mysql }.each do |pkg|
  describe package(pkg) do
    it { should be_installed }
  end
end

 バージョンも含めて確認する場合は以下となる。

# install check
describe package('mariadb-server') do
  it { should be_installed.with_version '5.5 }
end

2.サービスの起動と自動起動設定の確認

 サービスが起動していることと、自動起動が設定されていることの確認にはdescribe serviceを使用する。記述例は以下となる。

# service check
describe service('mariadb') do
  it { should be_enabled }
  it { should be_running }
end

3.指定ポートの待ち受け(LISTEN)確認

 サービスで指定したポートで待ち受け(LISTEN)状態になっていることの確認にはdescribe portを使用する。記述例は以下となる。

# httpd listen port check
describe port(80) do
  it { should be_listening }
end

4.ファイルの存在、内容、権限の確認

 サーバ上のファイルに対しての確認には原則、describe fileを使用する。

(1)ファイルの存在チェック

 指定されたファイルが存在するかのチェックの記述例は以下となる。

# wp-config.php file exits check
describe file("#{wp_dir}/wp-config.php") do
  it { should exist }
end

(2)ファイルの権限のチェック

 ファイルのuser/groupをチェックする記述例は以下となる。記述例では、特定フォルダ以下のファイルのリストを作成し、1個ずつuser/groupをチェックしていく処理になっている。実際に動作させたが、describe fileを1回処理するごとにssh接続が発生し処理に時間がかかり過ぎたため不採用としている。

wordpress file owner/group check (each file/reject)
wp_files = Specinfra.backend.run_command( "find #{wp_dir}" ).stdout.chop
wp_files.each_line { |wp_file| 
  describe file(wp_file.chomp) do
    it { should be_owned_by('root') }
    it { should be_grouped_into('root') }
  end
}

(3)ファイルの記述内容のチェック

 「ファイル内の指定の文字列が記述されているか」をチェックする記述例は以下の通り。ただ、この記述の場合、ファイル中に指定された文字列が存在することの確認はできるが、位置までは確認できないので注意が必要である。

# wp-config.php paramaters check
describe file("#{wp_dir}/wp-config.php") do
  it { should contain("define('DB_NAME',.*'#{wp_db_name}');") }
  it { should contain("define\('DB_USER',.*'#{wp_db_user}'\);")  }
  it { should contain("define\('DB_PASSWORD',.*'#{wp_db_pass}'\);")  }
  it { should contain("define\('AUTH_KEY',.*'#{wp_uniqe_phrse}'\);")  }
end

 containを使う以外にmatchを使う記述方法も存在する。containは廃止が予定されているため、新規に作成するのであれば、こちらのmatchを使用する方が望ましい。

# WordPress version check
describe file("#{wp_dir}/readme.html") do
  its(:content) { should match /Version #{wp_version}/ }
end

(4)ファイルの完全一致のチェック

 ファイルの記述内容が完全に想定通りになっているかをチェックする記述例は以下の通り。変数にファイルの内容を全て登録し、読み込んだファイルと完全に一致するかを比較している。<<"EOT"からEOTまでが前方の空白も含めて一致している必要があり、スクリプトのnestは無視する必要がある(比較対象のファイルの行がそのままコピーされている形に近い)。

# wordpress.conf check
wordpress_conf = <<"EOT"
<VirtualHost *:80>
  ServerName #{hostname}
  DocumentRoot #{wp_dir}
  <Directory "#{wp_dir}">
    AllowOverride All
    Options -Indexes
  </Directory>
  <Files wp-config.php>
    order allow,deny
    deny from all
  </Files>
</VirtualHost>
EOT
describe file("/etc/httpd/conf.d/wordpress.conf") do
  it { should contain wordpress_conf }
end

5.コマンドの実行確認

(1)コマンドの実行結果(exit code)のチェック

 コマンドの実行結果をチェックする記述例は以下となる。記述例はyum check-updateでupdate対象がない場合、exit code=0となることを利用して判定を行っている。

# yum update check
describe command("yum check-update") do
  its(:exit_status) { should eq 0 }
end

(2)コマンドの実行時の出力結果のチェック

 コマンドの実行結果の出力をチェックする記述例は以下となる。標準出力を対象としているため、:stdoutを使用しているが、エラー出力の場合は、:stderrを使用する。

# mysqladmin ping execute check
describe command( "mysqladmin ping" ) do
  its(:stdout) { should contain('mysqld is alive') }
end

(3)コマンド実行で件数を取得する出力結果のチェック

 コマンドを実行して、件数を取得し、その結果を基にチェックを行う記述例は以下となる。ある条件で検索した対象の行数や件数をwc -l やgrep -cで数値化する場合に有効な手段となる。

# wordpress file user/group check
describe command( "find #{wp_dir} -not -user #{wp_os_user} -or -not -group #{wp_os_group} | wc -l | tr -d '\n'" ) do
  its(:stdout) { should contain('^0$') }
end

 標準出力のため、改行コードが付与されてしまう。そのため、tr -dで改行コードを除去している。さらに0件に一致させるために'0'の前後に正規表現で'^'’(行頭を表すメタ文字)と'$'(行末表すメタ文字)を付与して判定を行っている。should containは「行中に指定文字列が含まれる」ことをチェックしているため、'0'のままでチェックを行うと、件数中に0が含まれる(例えば、10件とか909件とか)が正常と誤判定されてしまうこととなる。

(4)コマンド実行結果でチェック処理自体を分岐する

 ファイルの有無やシステムの状態によってチェック処理自体を変更する必要がある場合の記述例は以下の通り。

# mariadb logrotate test
already_rotate = Specinfra.backend.run_command( "sudo find /var/log/mariadb -name '*.gz' | wc -l" ).stdout.to_i
if already_rotate == 0  then
  describe command("logrotate -vf /etc/logrotate.d/mariadb") do
    its(:stdout) { should contain('running postrotate script') }
  end
else
  describe command("logrotate -vd /etc/logrotate.d/mariadb") do
    its(:stdout) { should contain('log does not need rotating') }
  end
end

 このテストケースでは、mariadb-serverのログローテーションを実際に行うことで検証した。ただ、ログローテーションが正常に行われている(すでにgzファイルが存在する)場合は、再実行を行わないよう制御している。

 また、lsコマンドでログファイルのgzファイルの件数を取得し、数値化したものを変数に格納している。0件だった場合はlogrotate -vfを、0件以外だった場合はlogrotate -vdを実行する。処理によって出力されるメッセージも異なるため、このような形で実装した。

6.Webサイトへのアクセス確認

「Webサイトにアクセスが行えるか」のチェックを以下の実装で行っている。今回はテストサーバ内部からcurlコマンドを利用して、トップページのURLにアクセスし、Body部に書かれている'WordPress'の文字列が取得できることで確認している。

hostname=host_inventory['hostname']
# httpd port open check
describe command("curl http://#{hostname}/wp-admin/install.php") do
  its(:stdout) { should contain('WordPress') }
end

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。