はじめに
前回、前々回の記事で capistrano
と Chef-Solo
を組み合わせたのをきっかけに AWS SDK for Ruby を使って EC2 インスタンスに対応させたツール的な物を作ったり serverspec を個人的に拡張したりしながら色々と学ぶことが多かったので、ツールで出来ることの棚卸しと学んだことについてメモる。
capistrano と Chef-Solo と AWS SDK for Ruby を組み合わせたツールについて
ソースコード
こちら。
イメージ
使い方
以下は README に反映させる予定。
EC2 のインスタンスを作成する
cap aws-setup ec2:launch
EC2 のインスタンスの一覧を取得する
cap aws-setup ec2:list
また、ec2:listall
で稼働中、停止中合わせて全てのインスタンスの一覧が表示される。
EC2 のインスタンスのタグを設定する
cap aws-setup ec2:settag -s _set_host="${Public_DNS}" -s _set_tag="${New_Tag}"
${Public_DNS}
でタグを設定するインスタンスを指定して、${New_Tag}
にて新しいタグを設定する。
ホスト(EC2 インスタンス、その他のサーバー)に Chef-Solo が利用出来るようにする
cap aws-setup chef:init
以下は EC2
インスタンスにかぎらず ssh
でログイン出来るホストであれば使える。
ホスト(EC2 インスタンス、その他のサーバー)に cookbook をアップロードする
cap aws-setup chef:sync
ホスト(EC2 インスタンス、その他のサーバー)で Chef-Solo を実行して cookbook を適用する
cap aws-setup chef:deploy
aws-setup
という名前だと AWS
に特化した感じになりそうなので将来的には名前を分けよう。
serverspec へのちょっとした拡張
ソースコード
こちら。
イメージ
使い方
以下は README に反映させる予定。
テスト対象となるホストの spec ファイルを作る
rake genspec
上記を実行すれば AWS SDK for Ruby
を経由してインスタンスのホスト名を取得して spec
ファイルのフォルダをテンプレートからコピーする。
ツールを作る過程で学んだこと
capistrano での #{sudo} と #{try_sudo} の違い
こちらに詳しく書かれていてとても参考になった。手元で試してみると以下のような違いが見られた。
set :use_sudo | sudo の書き方 | 展開されるコマンド結果 |
---|---|---|
false | #{try_sudo} | chef-solo -j /tmp/chef/chef-repo/nodes/localhost.json -c /tmp/chef/chef-repo/solo.rb |
true | #{try_sudo} | sudo -p 'sudo password: ' chef-solo -j /tmp/chef/chef-repo/nodes/localhost.json -c /tmp/chef/chef-repo/solo.rb |
false | #{sudo} | sudo -p 'sudo password: ' chef-solo -j /tmp/chef/chef-repo/nodes/localhost.json -c /tmp/chef/chef-repo/solo.rb |
true | #{sudo} | sudo -p 'sudo password: ' chef-solo -j /tmp/chef/chef-repo/nodes/localhost.json -c /tmp/chef/chef-repo/solo.rb |
上記の結果からすると set :use_sudo
を false
にしておいて #{sudo}
と書くのが EC2
インスタンスでは良さそう。
pry によるデバッグ
これもタイトル通り今更感満載だがツールを作る過程でデバッグと言えば、毎回 cap
コマンドを叩くという非効率なことをやっていたが、pry
を利用することでずいぶん効率化が図れた。起動はとても簡単。コマンドラインから pry
と打つだけ。
pry
起動すると以下のようなプロンプトになる。
AWS SDK for Ruby と pry
pry
から AWS SDK for Ruby を使う場合の最初の手続き的なものとして...
require 'aws-sdk'
AWS.config(:access_key_id => "AK******************", :secret_access_key => "****************************************", :region => "ap-northeast-1")
上記のように AWS SDK for Ruby を require
してからアクセスキー等の設定を行う。
上記では 1. と 2. を実行した後で dns_name
で指定したインスタンスの情報を取得しようとしているところ。結果は配列に入ったオブジェクトとして返ってくる。
配列に入ったオブジェクトからインスタンスの情報を取り出す
上記のように配列に入ったインスタンス情報のオブジェクトからインスタンス情報の詳細(インスタンスの ID や PublicDNS 等...)を取り出す場合には...
instance = AWS.ec2.instances.select {|i| i.status == :running && i.dns_name == "ec2-54-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com"}
上記の instance
には [<AWS::EC2::Instance id:i-xxxxxxxx>]
が入るので以下のようにした。
instance[0].instance_id instance[0].dns_name
以下はデモ。
dns_name
や instance_id
はメソッド。methods
でどんなメソッドがあるかを確認出来る。
Rakefile に纏めるとすっきりする
前回の記事で EC2
インスタンスに対して servespec
の spec
ファイルを生成する方法について別途でスクリプトを作って対応したが、この spec
ファイルを生成するスクリプトを Rakefile
に統合してしまった方が美しそうなのでやってみた。
require 'fileutils' require 'aws-sdk' require 'yaml' # task :genspec do config = YAML.load(File.read("#{ENV['HOME']}/path/to/config/deploy/config.yml")) AWS.config(config) # ORIG = "./spec_template" SPEC = "./spec" # servers = AWS.ec2.instances.select {|i| i.tags[:Name] == 'setup' && i.status == :running}.map(&:dns_name) servers.each do |server| puts "Created #{SPEC}/#{server}/check_spec.rb" FileUtils.cp_r("#{ORIG}","#{SPEC}""/""#{server}") unless FileTest.exist?(server) end end
上記のように Rakefile
に纏めることで手順としても以下のように rake
コマンドに集約することが出来た。
rake genspec
を実行すると spec
ファイルが生成(テンプレートからコピー)される。