nifty-cloud-sdk 1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 }