nifty-cloud-sdk 1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/CHANGELOG +112 -0
  2. data/Gemfile +4 -0
  3. data/INSTALL +30 -0
  4. data/LICENSE.txt +58 -0
  5. data/README.rdoc +375 -0
  6. data/Rakefile +61 -0
  7. data/lib/NIFTY.rb +405 -0
  8. data/lib/NIFTY/Cloud.rb +24 -0
  9. data/lib/NIFTY/Cloud/availability_zones.rb +23 -0
  10. data/lib/NIFTY/Cloud/certificates.rb +283 -0
  11. data/lib/NIFTY/Cloud/images.rb +134 -0
  12. data/lib/NIFTY/Cloud/instances.rb +372 -0
  13. data/lib/NIFTY/Cloud/keypairs.rb +76 -0
  14. data/lib/NIFTY/Cloud/load_balancers.rb +433 -0
  15. data/lib/NIFTY/Cloud/security_groups.rb +357 -0
  16. data/lib/NIFTY/Cloud/volumes.rb +140 -0
  17. data/lib/NIFTY/config.rb +41 -0
  18. data/lib/NIFTY/exceptions.rb +32 -0
  19. data/lib/NIFTY/responses.rb +19 -0
  20. data/lib/NIFTY/version.rb +3 -0
  21. data/nifty-cloud-sdk.gemspec +28 -0
  22. data/sample/availability_zones/describe-availability-zones.rb +37 -0
  23. data/sample/certificate/create-ssl-certificate.rb +41 -0
  24. data/sample/certificate/delete-ssl-certificate.rb +28 -0
  25. data/sample/certificate/describe-ssl-certificate-attribute.rb +58 -0
  26. data/sample/certificate/describe-ssl-certificates.rb +49 -0
  27. data/sample/certificate/download-ssl-certificate.rb +31 -0
  28. data/sample/certificate/modify-ssl-certificate-attribute.rb +29 -0
  29. data/sample/certificate/register-corporate-info-for-certificate.rb +57 -0
  30. data/sample/certificate/upload-ssl-certificate.rb +32 -0
  31. data/sample/images/create-image.rb +33 -0
  32. data/sample/images/delete-image.rb +26 -0
  33. data/sample/images/describe-images.rb +70 -0
  34. data/sample/images/modify-image-attribute.rb +33 -0
  35. data/sample/instances/cancel_copy_instances.rb +26 -0
  36. data/sample/instances/copy-instances.rb +41 -0
  37. data/sample/instances/describe-instance-attribute.rb +78 -0
  38. data/sample/instances/describe-instances.rb +100 -0
  39. data/sample/instances/modify-instance-attribute.rb +30 -0
  40. data/sample/instances/reboot-instances.rb +29 -0
  41. data/sample/instances/run-instances.rb +104 -0
  42. data/sample/instances/start-instances.rb +36 -0
  43. data/sample/instances/stop-instances.rb +35 -0
  44. data/sample/instances/terminate-instances.rb +34 -0
  45. data/sample/keypairs/create-key-pair.rb +31 -0
  46. data/sample/keypairs/delete-key-pair.rb +28 -0
  47. data/sample/keypairs/describe-key-pairs.rb +31 -0
  48. data/sample/load_balancers/configure-health-check.rb +41 -0
  49. data/sample/load_balancers/create-load-balancer.rb +35 -0
  50. data/sample/load_balancers/delete-load-balancer.rb +28 -0
  51. data/sample/load_balancers/deregister-instances-from-load-balancer.rb +35 -0
  52. data/sample/load_balancers/describe-instance-health.rb +36 -0
  53. data/sample/load_balancers/describe-load-balancers.rb +89 -0
  54. data/sample/load_balancers/register-instances-with-load-balancer.rb +33 -0
  55. data/sample/load_balancers/register-port-with-load-balancer.rb +37 -0
  56. data/sample/load_balancers/set-filter-for-load-balancer.rb +38 -0
  57. data/sample/load_balancers/update-load-balancer.rb +33 -0
  58. data/sample/security_groups/authorize-security-group-ingress.rb +36 -0
  59. data/sample/security_groups/create-security-group.rb +29 -0
  60. data/sample/security_groups/delete-security-group.rb +28 -0
  61. data/sample/security_groups/deregister-instances-from-security-group.rb +31 -0
  62. data/sample/security_groups/describe-security-activities.rb +33 -0
  63. data/sample/security_groups/describe-security-groups.rb +59 -0
  64. data/sample/security_groups/register-instances-with-security-group.rb +31 -0
  65. data/sample/security_groups/revoke-security-group-ingress.rb +36 -0
  66. data/sample/security_groups/update-security-group.rb +30 -0
  67. data/sample/volumes/attach-volumes.rb +34 -0
  68. data/sample/volumes/create-volume.rb +38 -0
  69. data/sample/volumes/delete-volume.rb +28 -0
  70. data/sample/volumes/describe-volumes.rb +44 -0
  71. data/sample/volumes/detach-volume.rb +35 -0
  72. data/test/test_Cloud.rb +186 -0
  73. data/test/test_Cloud_availability_zones.rb +50 -0
  74. data/test/test_Cloud_certificates.rb +627 -0
  75. data/test/test_Cloud_images.rb +284 -0
  76. data/test/test_Cloud_instances.rb +941 -0
  77. data/test/test_Cloud_keypairs.rb +177 -0
  78. data/test/test_Cloud_load_balancers.rb +1183 -0
  79. data/test/test_Cloud_responses.rb +43 -0
  80. data/test/test_Cloud_security_groups.rb +699 -0
  81. data/test/test_Cloud_volumes.rb +325 -0
  82. data/test/test_helper.rb +23 -0
  83. metadata +275 -0
@@ -0,0 +1,61 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ begin
12
+ require 'rcov/rcovtask'
13
+ Rcov::RcovTask.new do |test|
14
+ test.libs << 'test'
15
+ test.pattern = 'test/test_*.rb'
16
+ test.verbose = true
17
+ test.rcov_opts << "--exclude /gems/,/Library/,spec"
18
+ end
19
+ rescue LoadError
20
+ task :rcov do
21
+ abort "RCov is not available. In order to run rcov, you must: [sudo] gem install rcov"
22
+ end
23
+ end
24
+
25
+ task :default => :test
26
+
27
+ require 'rake/rdoctask'
28
+ Rake::RDocTask.new do |rdoc|
29
+ if File.exist?('VERSION.yml')
30
+ config = YAML.load(File.read('VERSION.yml'))
31
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
32
+ else
33
+ version = ""
34
+ end
35
+
36
+ rdoc.rdoc_dir = 'rdoc'
37
+ rdoc.title = "NIFTY Cloud SDK documentation"
38
+ rdoc.main = "README.rdoc"
39
+ rdoc.rdoc_files.include('README*')
40
+ rdoc.rdoc_files.include('LICENSE*')
41
+ rdoc.rdoc_files.include('lib/**/*.rb')
42
+ rdoc.options << '--line-numbers'
43
+ rdoc.options << '-c UTF-8'
44
+ end
45
+
46
+ begin
47
+ require 'yard'
48
+ YARD::Rake::YardocTask.new do |t|
49
+ #t.files = ['lib/**/*.rb']
50
+ end
51
+ rescue LoadError
52
+ puts "YARD (or a dependency) not available. Install it with: [sudo] gem install yard"
53
+ end
54
+
55
+ desc "Generate a perftools.rb profile"
56
+ task :profile do
57
+ system("CPUPROFILE=perftools/ec2prof RUBYOPT=\"-r`gem which perftools | tail -1`\" ruby sample/describe-instances.rb")
58
+ system("pprof.rb --text --ignore=Gem perftools/ec2prof > perftools/ec2prof-results.txt")
59
+ system("pprof.rb --dot --ignore=Gem perftools/ec2prof > perftools/ec2prof-results.dot")
60
+ end
61
+
@@ -0,0 +1,405 @@
1
+ #--
2
+ # ニフティクラウドSDK for Ruby
3
+ #
4
+ # Ruby Gem Name:: nifty-cloud-sdk
5
+ # Author:: NIFTY Corporation
6
+ # Copyright:: Copyright 2011 NIFTY Corporation All Rights Reserved.
7
+ # License:: Distributes under the same terms as Ruby
8
+ # Home:: http://cloud.nifty.com/api/
9
+ #++
10
+
11
+ %w[ base64 cgi openssl digest/sha1 net/https net/http rexml/document time ostruct ipaddr logger ].each { |f| require f }
12
+
13
+ begin
14
+ require 'URI' unless defined? URI
15
+ rescue Exception => e
16
+ # nothing
17
+ end
18
+
19
+ begin
20
+ require 'xmlsimple' unless defined? XmlSimple
21
+ rescue Exception => e
22
+ require 'xml-simple' unless defined? XmlSimple
23
+ end
24
+
25
+ # Hashの値をドット表記で取得可能とするための、Hashクラスに独自のメソッド定義を行う
26
+ #
27
+ # @example 次のような形でHashの値を取得することができる
28
+ # foo[:bar] => "baz"
29
+ # foo.bar => "baz"
30
+ class Hash
31
+ def method_missing(meth, *args, &block)
32
+ if args.size == 0
33
+ self[meth.to_s] || self[meth.to_sym]
34
+ end
35
+ end
36
+
37
+ def type
38
+ self['type']
39
+ end
40
+
41
+ def has?(key)
42
+ self[key] && !self[key].to_s.empty?
43
+ end
44
+
45
+ def does_not_have?(key)
46
+ self[key].nil? || self[key].to_s.empty?
47
+ end
48
+ end
49
+
50
+
51
+ module NIFTY
52
+ LOG = Logger.new(STDOUT)
53
+ #LOG.level = Logger::DEBUG
54
+ LOG.level = Logger::INFO
55
+
56
+ # 署名パラメータ文字列生成
57
+ # urlencodeが真の場合はURLエンコードを行い、偽の場合はエンコードしない
58
+ #
59
+ def NIFTY.encode(secret_key, str, key_type, urlencode=true)
60
+ digest = OpenSSL::Digest::Digest.new(key_type)
61
+ b64_hmac = Base64.encode64(OpenSSL::HMAC.digest(digest, secret_key, str)).strip
62
+
63
+ if urlencode
64
+ return CGI::escape(b64_hmac)
65
+ else
66
+ return b64_hmac
67
+ end
68
+ end
69
+
70
+ # HTTPリクエストの生成、実行、レスポンス解析を行う共通クラス
71
+ class Base
72
+ DEFAULT_CONNECTION_TIMEOUT = 30
73
+ DEFAULT_SOCKET_TIMEOUT = 30
74
+ DEFAULT_PORT = 443
75
+ DEFAULT_CONTENT_TYPE = 'application/x-www-form-urlencoded;charset=UTF-8'
76
+ PROTOCOL_HTTPS = 'https'
77
+ SIGNATURE_METHOD_SHA1 = 'HmacSHA1'
78
+ SIGNATURE_METHOD_SHA256 = 'HmacSHA256'
79
+ PORT_RANGE = (0..65535)
80
+ SIGNATURE_VERSION = ["0", "1", "2"]
81
+
82
+ attr_reader :access_key, :secret_key, :use_ssl, :server, :path, :proxy_server, :port, :connection_timeout, :socket_timeout,
83
+ :user_agent, :max_retry, :signature_version, :signature_method
84
+
85
+ # オプションを指定してニフティクラウドAPIクライアントを生成します。
86
+ #
87
+ # @option options [String] :access_key 公開キー
88
+ # @option options [String] :secret_key 秘密キー
89
+ # @option options [Boolean] :use_ssl SSL暗号化(true or false)
90
+ # @option options [String] :server APIホスト
91
+ # @option options [String] :path APIパス
92
+ # @option options [String] :proxy_server プロキシサーバーのURL
93
+ # @option options [String] :port 接続先ポート番号
94
+ # @option options [Integer] :connection_timeout 接続タイムアウト(秒)
95
+ # @option options [Integer] :socket_timeout ソケットタイムアウト(秒)
96
+ # @option options [String] :user_agent ユーザーエージェント
97
+ # @option options [Integer] :max_retry 最大リトライ回数
98
+ # @option options [String] :signature_version 認証バージョン
99
+ # @option options [String] :signature_method APIの認証ロジック
100
+ #
101
+ # @return [Base] ニフティクラウドAPIクライアントオブジェクト
102
+ #
103
+ def initialize( options = {} )
104
+ @default_host = @default_path = @default_port = nil
105
+
106
+ if blank?(options[:server])
107
+ # options[:server]の指定がない場合はデフォルトのエンドポイントを使用する
108
+ raise ConfigurationError, "No ENDPOINT_URL provided." if blank?(@default_endpoint)
109
+ uri = URI.parse(@default_endpoint)
110
+ raise ConfigurationError, "Invalid ENDPOINT_URL provided." unless PROTOCOL_HTTPS == uri.scheme
111
+ @default_host = uri.host || (raise ConfigurationError, "Invalid ENDPOINT_URL provided.")
112
+ @default_path = uri.path
113
+ @default_port = uri.port
114
+ end
115
+
116
+ options = {
117
+ :access_key => @default_access_key,
118
+ :secret_key => @default_secret_key,
119
+ :use_ssl => true,
120
+ :server => @default_host,
121
+ :path => @default_path,
122
+ :proxy_server => @default_proxy_server,
123
+ :port => @default_port,
124
+ :connection_timeout => @default_connection_timeout,
125
+ :socket_timeout => @default_socket_timeout,
126
+ :user_agent => @default_user_agent,
127
+ :max_retry => @default_max_retry,
128
+ :signature_version => @default_signature_version,
129
+ :signature_method => @default_signature_method
130
+ }.merge(options)
131
+
132
+ options[:port] = DEFAULT_PORT if blank?(options[:port])
133
+
134
+ raise ArgumentError, "No :access_key provided." if blank?(options[:access_key])
135
+ raise ArgumentError, "No :secret_key provided." if blank?(options[:secret_key])
136
+ raise ArgumentError, "No :use_ssl provided." if blank?(options[:use_ssl])
137
+ raise ArgumentError, "Invalid :use_ssl provided. only 'true' allowed." unless true == options[:use_ssl]
138
+ raise ArgumentError, "No :server provided." if blank?(options[:server])
139
+ raise ArgumentError, "No :path provided." if blank?(options[:path])
140
+ raise ArgumentError, "Invalid :port provided." unless valid_port?(options[:port])
141
+ raise ArgumentError, "Invalid :signature_version provided." unless SIGNATURE_VERSION.include?(options[:signature_version].to_s)
142
+ raise ArgumentError, "Invalid :signature_method provided." unless [SIGNATURE_METHOD_SHA1, SIGNATURE_METHOD_SHA256].include?(options[:signature_method].to_s)
143
+
144
+ @access_key = options[:access_key].to_s
145
+ @secret_key = options[:secret_key].to_s
146
+ @use_ssl = options[:use_ssl]
147
+ @server = options[:server].to_s
148
+ @path = options[:path].to_s
149
+ @proxy_server = options[:proxy_server].to_s
150
+ @port = options[:port].to_i
151
+ @connection_timeout = options[:connection_timeout].to_s.to_i
152
+ @socket_timeout = options[:socket_timeout].to_s.to_i
153
+ @user_agent = options[:user_agent].to_s
154
+ @max_retry = options[:max_retry].to_s.to_i
155
+ @signature_version = options[:signature_version].to_s
156
+ @signature_method = options[:signature_method].to_s
157
+
158
+ make_http
159
+ end
160
+
161
+ private
162
+ def make_http
163
+ proxy = @proxy_server ? URI.parse(@proxy_server) : OpenStruct.new
164
+ @http = Net::HTTP::Proxy( proxy.host,
165
+ proxy.port,
166
+ proxy.user,
167
+ proxy.password ).new(@server, @port)
168
+
169
+ LOG.debug("[URL]https://#{@server}#{":" + @port.to_s unless @port == 443}#{@path}")
170
+ LOG.debug("[PROXY]#{@proxy_server}") unless blank?(@proxy_server)
171
+
172
+ @http.use_ssl = @use_ssl
173
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
174
+ @http.open_timeout = (@connection_timeout >= 0) ? @connection_timeout : DEFAULT_CONNECTION_TIMEOUT
175
+ @http.read_timeout = (@socket_timeout > 0) ? @socket_timeout : DEFAULT_SOCKET_TIMEOUT
176
+ end
177
+
178
+ # :user_dataオプションを指定された際、:base64_encodedオプションの値がtrueならば
179
+ # :user_dataに対しBase64エンコードを行う
180
+ private
181
+ def extract_user_data( options = {} )
182
+ return unless options[:user_data]
183
+ if options[:user_data]
184
+ if options[:base64_encoded]
185
+ return Base64.encode64(options[:user_data]).gsub(/\n/, "").strip
186
+ else
187
+ return options[:user_data]
188
+ end
189
+ end
190
+ end
191
+
192
+ # パラメータ名のリストを生成したい場合に使用する
193
+ #
194
+ # @example
195
+ # 入力: key = 'ImageId',
196
+ # arr = ['123', '456'])
197
+ # 出力: {"ImageId.1"=>"123", "ImageId.2"=>"456"}
198
+ #
199
+ private
200
+ def pathlist(key, arr)
201
+ raise ArgumentError, "expected a key that is a String" unless key.is_a?(String)
202
+ raise ArgumentError, "unexpected a key that is empty" if key.empty?
203
+
204
+ params = {}
205
+ [arr].flatten.delete_if{ |value| blank?(value) }.each_with_index{ |value, i| params["#{key}.#{i+1}"] = value.to_s }
206
+
207
+ return params
208
+ end
209
+
210
+ # パラメータグループのリストを生成したい場合に使用する
211
+ #
212
+ # @example
213
+ # 入力: key = 'People',
214
+ # arr_of_hashes = [{:name=>'jon', :age=>'22'}, {:name=>'chris'}],
215
+ # mappings = {:name => 'Name', :age => 'Age'}
216
+ # 出力: {"People.1.Name"=>"jon", "People.1.Age"=>'22', 'People.2.Name'=>'chris'}
217
+ #
218
+ private
219
+ def pathhashlist(key, arr_of_hashes, mappings, key_name_mappings={})
220
+ arr_of_hashes = [arr_of_hashes].flatten
221
+ raise ArgumentError, "expected a key that is a String" unless key.is_a?(String)
222
+ raise ArgumentError, "unexpected a key that is empty" if key.empty?
223
+ arr_of_hashes.each{|h| raise ArgumentError, "expected each element of arr_of_hashes to be a Hash" unless h.is_a?(Hash)}
224
+ raise ArgumentError, "expected a mappings that is an Hash" unless mappings.is_a?(Hash)
225
+ raise ArgumentError, "expected a key_name_mappings that is an Hash" unless blank?(key_name_mappings) || key_name_mappings.is_a?(Hash)
226
+
227
+ params = {}
228
+ i = 0
229
+ arr_of_hashes.each do |hash|
230
+ param_size = params.size
231
+ hash.each do |attribute, value|
232
+ next if blank?(attribute) || blank?(mappings[attribute]) || blank?(value)
233
+ if value.is_a? Array
234
+ j = 0
235
+ value.each do |item|
236
+ next if blank?(item)
237
+ param_name = "#{key}.#{i+1}.#{mappings[attribute]}.#{j+1}"
238
+ param_name << ".#{key_name_mappings[attribute]}" unless blank?(key_name_mappings[attribute])
239
+ params[param_name] = item.to_s
240
+ j += 1
241
+ end
242
+ else
243
+ params["#{key}.#{i+1}.#{mappings[attribute]}"] = value.to_s
244
+ end
245
+ end
246
+ i += 1 if params.size > param_size
247
+ end
248
+
249
+ return params
250
+ end
251
+
252
+ # オプションで指定されたキー名を送信用パラメータのキー名に変換し、パラメータを生成する
253
+ # prefixが指定されている場合はキー名の先頭に付加する
254
+ #
255
+ # @example
256
+ # 入力: options = {:opt1 => "val1", :opt2 => "val2", :opt3 => "val3"},
257
+ # arr = [:opt1, :opt2],
258
+ # prefix = "Param"
259
+ # 出力: {"Param.Opt1 => "val1", "Param.Opt2" => "val2"}
260
+ #
261
+ private
262
+ def opts_to_prms( options={}, arr=nil, prefix=nil)
263
+ params = {}
264
+ arr = options.keys if arr.nil?
265
+ arr.each do |o|
266
+ key = o.to_s.split('_').collect { |s| s.capitalize }.join
267
+ key.insert(0, "#{prefix}.") unless blank?(prefix)
268
+ params[key] = options[o].to_s unless blank?(options[o])
269
+ end
270
+
271
+ return params
272
+ end
273
+
274
+ # オブジェクトの文字列表現が空の場合は
275
+ # trueを返却する
276
+ private
277
+ def blank?( obj )
278
+ obj.to_s.empty?
279
+ end
280
+
281
+ # ポートチェック
282
+ # ポート番号が正しい場合はtrue、そうでなければfalseを返却する
283
+ private
284
+ def valid_port?( port )
285
+ return false unless /^\d+$/ =~ port.to_s
286
+ return PORT_RANGE.include?(port.to_s.to_i)
287
+ end
288
+
289
+ # HTTPリクエスト生成
290
+ private
291
+ def make_request(params)
292
+ params.reject! { |key, value| blank?(value) }
293
+
294
+ params.merge!( {'SignatureVersion' => @signature_version,
295
+ 'SignatureMethod' => @signature_method,
296
+ 'AccessKeyId' => @access_key,
297
+ 'Version' => VERSION,
298
+ 'Timestamp' => Time.now.getutc.iso8601.sub(/Z/, sprintf(".%03dZ",(Time.now.getutc.usec/1000)))} )
299
+
300
+ @encoded_params = params.sort.collect { |param|
301
+ "#{CGI::escape(param[0])}=#{CGI::escape(param[1])}"
302
+ }.join("&").gsub('+', '%20').gsub('%7E', '~')
303
+
304
+ sig = get_auth_param(params, @secret_key)
305
+
306
+ query = "#{@encoded_params}&Signature=#{sig}"
307
+
308
+ LOG.debug("[QUERY]#{query}")
309
+
310
+ req = Net::HTTP::Post.new(@path)
311
+ req.content_type = DEFAULT_CONTENT_TYPE
312
+ req['User-Agent'] = @user_agent unless blank?(@user_agent)
313
+ req.body = query
314
+
315
+ return req
316
+ end
317
+
318
+ # HTTPリクエスト実行
319
+ private
320
+ def exec_request(req)
321
+ retry_cnt = 0
322
+ sleep_time = 300 / 1000.0
323
+
324
+ begin
325
+ @http.start do
326
+ return @http.request(req)
327
+ end
328
+ rescue TimeoutError => e
329
+ # タイムアウトが発生した場合はリトライする
330
+ raise e if retry_cnt >= @max_retry
331
+ sleep(sleep_time)
332
+ LOG.warn("HTTP retry. #{e.message}")
333
+ retry_cnt += 1
334
+ retry
335
+ end
336
+ end
337
+
338
+ # 署名パラメータ設定
339
+ private
340
+ def get_auth_param(params, secret_key)
341
+ if params["SignatureVersion"].to_i < 2
342
+ key_type = SIGNATURE_METHOD_SHA1
343
+ else
344
+ key_type = params["SignatureMethod"]
345
+ end
346
+
347
+ canonical_string = make_canonical(params)
348
+ LOG.debug("[SIGN]" + canonical_string.gsub(/\n/, "(\\n)"))
349
+
350
+ return NIFTY.encode(secret_key, canonical_string, key_type.downcase.gsub(/hmac/, ''))
351
+ end
352
+
353
+ # 署名パラメータ生成用文字列の生成
354
+ private
355
+ def make_canonical(params=[])
356
+ case params["SignatureVersion"]
357
+ when '0'
358
+ return "#{params['Action']}#{params['Timestamp']}"
359
+ when '1'
360
+ return params.sort.join
361
+ when '2'
362
+ return ['POST', @server, @path, @encoded_params].join("\n")
363
+ end
364
+ end
365
+
366
+ # レスポンスXMLの解析を行う
367
+ # エラーレスポンスの場合は例外を発生させる
368
+ private
369
+ def response_generator( params={} )
370
+
371
+ LOG.debug('[ACTION]' + params['Action'])
372
+ http_response = exec_request(make_request(params))
373
+
374
+ return Response.parse(:xml => http_response.body) unless response_error?(http_response)
375
+ end
376
+
377
+ # レスポンスのエラーチェック
378
+ private
379
+ def response_error?(response)
380
+
381
+ #LOG.debug('[BODY]' + response.body)
382
+
383
+ # 正常レスポンスの場合はfalseを返却する
384
+ return false if response.is_a?(Net::HTTPSuccess)
385
+
386
+ # XML形式チェック
387
+ # 形式が不正な場合は例外を発生させる
388
+ begin
389
+ doc = REXML::Document.new(response.body)
390
+
391
+ # エラーXML形式:
392
+ # <?xml version="1.0"?><Response><Errors><Error><Code>Client.InvalidInstanceID.NotFound</Code><Message>The instance ID 'foo' does not exist.</Message>
393
+ # </Error></Errors><RequestID>291cef62-3e86-414b-900e-17246eccfae8</RequestID></Response>
394
+ error_code = doc.root.elements['Errors'].elements['Error'].elements['Code'].text
395
+ error_message = doc.root.elements['Errors'].elements['Error'].elements['Message'].text
396
+ rescue
397
+ raise ResponseFormatError, "Unexpected error format. response.body is: #{response.body}"
398
+ end
399
+
400
+ raise ResponseError.new(error_code, error_message)
401
+ end
402
+ end # end of Base class
403
+ end # end of NIFTY module
404
+
405
+ Dir[File.join(File.dirname(__FILE__), 'NIFTY/**/*.rb')].sort.each { |lib| require lib }