LoginSignup
38
42

More than 5 years have passed since last update.

AWS SDK for Ruby v2のwaitersの解説

Last updated at Posted at 2014-12-02

何の機能か?

AWSのAPIは、基本的にあるリクエストに対するレスポンスを即座に返してしまい、そのリクエストで意図した結果が必ず起こるとは限りません。
APIリクエストに成功すると、HTTPコード200 とともにインスタンスの情報が返ってきます。

ですが、HTTP 200を受け取ったからといって、このインスタンスがrunningになるとは限りません。
APIレスポンスが返ってきた後、その対象が望むべきStatusになっているかどうかを暫くの間監視しておく必要があります。
このような場合aws-sdk v2から導入されたwaitersを使うと便利です。

まずv2をインストール

gem 'aws-sdk', '2.0.11.pre'
gem 'aws-sdk-core'

環境変数をセットしておくこと

$ export AWS_ACCESS_KEY_ID=XXXXXXXXXXXXX
$ export AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$ export AWS_REGION=ap-northeast-1

使い方の例

簡単な使い方

wait_untilメソッドで処理をブロックしています。

require 'aws-sdk'

ec2 = Aws::EC2::Client.new
ec2.start_instances(instance_ids: ['i-12345678'])
ec2.wait_until(:instance_running,  instance_ids:['i-12345678'])

waitの細かい制御方法

以下のケースは一時間ec2が起動するまで待つ例です。(15秒おきに240回待つ)

ec2 = Aws::EC2::Client.new
ec2.wait_until(:instance_running, instance_ids:['i-12345678']) do |w|
  w.interval = 15
  w.max_attempts = 240
end

RDSでDBがavailableになるまで待つ

rds.create_db_instance(db_instance_identifier:'db01')
rds.wait_until(:db_instance_available, db_instance_identifier:'db01')
  • 与えるパラメータもResourceによって違うので注意

interval毎に処理を挟む

ec2 = Aws::EC2::Client.new
ec2.wait_until(:instance_running, instance_ids:['i-12345678']) do |w|
  w.before_attempt do |attempt|
    puts "before interval..."
  end

  w.before_wait do |attempt, prev_response|
    puts "after interval..."
  end
end
  • before_waitはintervalの後に処理を挟むことが出来る
  • before_attemptはintervalの前に処理を挟むことが出来る

rescueでエラーを拾う

指定時間待ってもステータスが変わらない場合、Aws::Waiters::Errors::WaiterFailedが発生する。

ec2 = Aws::EC2::Client.new

begin
  ec2.wait_until(:instance_running,  instance_ids:['i-1234567']) do |w|
    w.interval = 15
    w.max_attempts = 240
  end
rescue Aws::Waiters::Errors::WaiterFailed => error
  puts "failed waiting for instance running: #{error.message}"
end

Resource別statusの確認

主なResourceのstatusを調べてみる。

wait_untilの引数にすればそのステータスになるまで処理をブロックできます。

EC2

Aws::EC2::Client.new.waiter_names
=> [:system_status_ok,
 :instance_status_ok,
 :image_available,
 :instance_running,
 :instance_stopped,
 :instance_terminated,
 :export_task_completed,
 :export_task_cancelled,
 :snapshot_completed,
 :subnet_available,
 :volume_available,
 :volume_in_use,
 :volume_deleted,
 :vpc_available,
 :vpn_connection_available,
 :vpn_connection_deleted,
 :bundle_task_complete,
 :conversion_task_completed,
 :conversion_task_cancelled,
 :customer_gateway_available,
 :conversion_task_deleted,
 :spot_instance_request_fulfilled]

S3

Aws::S3::Client.new.waiter_names
=> [:bucket_exists, :bucket_not_exists, :object_exists, :object_not_exists]

RDS

Aws::RDS::Client.new.waiter_names
=> [:db_instance_available, :db_instance_deleted]

Redshift

Aws::Redshift::Client.new.waiter_names
=> [:cluster_available, :cluster_deleted, :snapshot_available]

DynamoDB

Aws::DynamoDB::Client.new.waiter_names
=> [:table_exists, :table_not_exists]

ステータスが存在しないケース

Aws::EMR::Client.new.waiter_names
=> []
  • ElastiCache、Kinesis、SQSなどもステータスが存在しません。

まとめ

APIリクエスト後Statusの値をintervalを設けてPollingし、何回以内に成功しなければ異常と判断されるので例外を投げると言った処理を自分で作っていたかと思うのですが、その部分をSDKで吸収してくれるようになりました。

38
42
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
42