前回はノード属性を使って汎用的なレシピを書く方法を紹介しました。汎用的なレシピは様々な環境で利用できるので,
プラグイン
Itamaeにはプラグイン機構が用意されていて,
レシピプラグイン
レシピプラグインを作ることで,itamae-plugin-recipe-(レシピ名)
の形式にする必要があります。rubygems.itamae-plugin-recipe
を検索すると既存のプラグインを探すことができます。
ここでは例としてnginx用のレシピプラグインを作ってみたいと思います。まず,bundle gem
コマンドを使って,
$ bundle gem itamae-plugin-recipe-nginx
gemspecファイルにTODO
が含まれていると,
レシピはlib/
に書くことで,include_
で読み込むことができます。また,lib/
のように同じディレクトリにレシピを配置すると,include_
またはinclude_
で読み込むことができます。
lib/
:
node.reverse_merge!(
nginx: {
user: 'www-data',
worker_processes: 4,
}
)
package 'nginx' do
version node['nginx']['version'] if node['nginx']['version']
end
service 'nginx'
template '/etc/nginx/nginx.conf' do
owner 'root'
group 'root'
mode '644'
notifies :reload, 'service[nginx]'
end
lib/
:
user <%= node['nginx']['user'] %>;
worker_processes <%= node['nginx']['worker_processes'] %>;
pid /run/nginx.pid;
events {
worker_connections 768;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
gzip_disable "msie6";
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
レシピやテンプレートの書き方は通常のレシピと同様です。できるだけ様々なシーンで利用できるように,node
の値を参照して柔軟に設定できるようにしておくことをお勧めします。このレシピが期待通り動くかどうかをServerspecでテストしましょう。Serverspecはサーバの状態を記述して想定通りの状態になっているかどうかをテストするためのフレームワークです。
まず,
spec.add_development_dependency "bundler", "~> 1.10"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec"
+ spec.add_development_dependency "serverspec"
end
テストはVagrantで起動した仮想マシンに対して実行するので,Vagrantfile
を生成します。なお,
$ vagrant init -m ubuntu/trusty64
Serverspec用の設定を書きます。spec/
に以下を記述します。
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
require 'serverspec'
require 'net/ssh'
require 'tmpdir'
set :backend, :ssh
if ENV['ASK_SUDO_PASSWORD']
begin
require 'highline/import'
rescue LoadError
fail "highline is not available. Try installing it."
end
set :sudo_password, ask("Enter sudo password: ") { |q| q.echo = false }
else
set :sudo_password, ENV['SUDO_PASSWORD']
end
# Vagrantを使って仮想マシンを起動します
system "vagrant", "up", "default"
ssh_options = nil
config = Tempfile.new("itamae")
config.write(`vagrant ssh-config default`)
config.close
ssh_options = Net::SSH::Config.for("default", [config.path])
config.unlink
ssh_options[:user] ||= Etc.getlogin
set :host, ssh_options[:host_name]
set :ssh_options, ssh_options
Serverspecのテストを記述します。
require 'spec_helper'
require 'itamae'
describe Itamae::Plugin::Recipe::Nginx do
before(:all) do
Itamae.logger.level = ::Logger::INFO
# SSHでVagrantのホストに対してItamaeを実行します
backend = Itamae::Backend.create("ssh", {vagrant: true, sudo: true})
backend.run_command(%w!apt-get update!)
runner = Itamae::Runner.new(backend, {})
runner.load_recipes([File.expand_path("lib/itamae/plugin/recipe/nginx/default.rb")])
runner.run(dry_run: false)
end
# nginxパッケージがインストールされていること
describe package('nginx') do
it { is_expected.to be_installed }
end
# nginxサービスが実行中であること
describe service('nginx') do
it { is_expected.to be_running }
end
# nginxのワーカプロセスが4つ起動していること
describe command('ps aux | grep [n]ginx | grep worker | wc -l') do
its(:stdout) { is_expected.to eq("4\n") }
end
end
BundlerでServerspecをインストールし,
$ bundle install $ bundle exec rake spec (中略) Itamae::Plugin::Recipe::Nginx INFO : Recipe: /Users/ryota-arai/src/github.com/ryotarai/itamae-plugin-recipe-nginx/lib/itamae/plugin/recipe/nginx/default.rb Package "nginx" should be installed Service "nginx" should be running Command "ps aux | grep [n]ginx | grep worker | wc -l" stdout should eq "4\n" Finished in 16.68 seconds (files took 7.82 seconds to load) 3 examples, 0 failures
ItamaeがVagrantの仮想マシンに実行された後,rake release
でリリースします。
$ bundle exec rake release