aspera-cli 4.0.0.pre1

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 (88) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +3592 -0
  3. data/bin/ascli +7 -0
  4. data/bin/asession +89 -0
  5. data/docs/Makefile +59 -0
  6. data/docs/README.erb.md +3012 -0
  7. data/docs/README.md +13 -0
  8. data/docs/diagrams.txt +49 -0
  9. data/docs/secrets.make +38 -0
  10. data/docs/test_env.conf +117 -0
  11. data/docs/transfer_spec.html +99 -0
  12. data/examples/aoc.rb +17 -0
  13. data/examples/proxy.pac +60 -0
  14. data/examples/transfer.rb +115 -0
  15. data/lib/aspera/api_detector.rb +60 -0
  16. data/lib/aspera/ascmd.rb +151 -0
  17. data/lib/aspera/ats_api.rb +43 -0
  18. data/lib/aspera/cli/basic_auth_plugin.rb +38 -0
  19. data/lib/aspera/cli/extended_value.rb +88 -0
  20. data/lib/aspera/cli/formater.rb +238 -0
  21. data/lib/aspera/cli/listener/line_dump.rb +17 -0
  22. data/lib/aspera/cli/listener/logger.rb +20 -0
  23. data/lib/aspera/cli/listener/progress.rb +52 -0
  24. data/lib/aspera/cli/listener/progress_multi.rb +91 -0
  25. data/lib/aspera/cli/main.rb +304 -0
  26. data/lib/aspera/cli/manager.rb +440 -0
  27. data/lib/aspera/cli/plugin.rb +90 -0
  28. data/lib/aspera/cli/plugins/alee.rb +24 -0
  29. data/lib/aspera/cli/plugins/ats.rb +231 -0
  30. data/lib/aspera/cli/plugins/bss.rb +71 -0
  31. data/lib/aspera/cli/plugins/config.rb +806 -0
  32. data/lib/aspera/cli/plugins/console.rb +62 -0
  33. data/lib/aspera/cli/plugins/cos.rb +106 -0
  34. data/lib/aspera/cli/plugins/faspex.rb +377 -0
  35. data/lib/aspera/cli/plugins/faspex5.rb +93 -0
  36. data/lib/aspera/cli/plugins/node.rb +438 -0
  37. data/lib/aspera/cli/plugins/oncloud.rb +937 -0
  38. data/lib/aspera/cli/plugins/orchestrator.rb +169 -0
  39. data/lib/aspera/cli/plugins/preview.rb +464 -0
  40. data/lib/aspera/cli/plugins/server.rb +216 -0
  41. data/lib/aspera/cli/plugins/shares.rb +63 -0
  42. data/lib/aspera/cli/plugins/shares2.rb +114 -0
  43. data/lib/aspera/cli/plugins/sync.rb +65 -0
  44. data/lib/aspera/cli/plugins/xnode.rb +115 -0
  45. data/lib/aspera/cli/transfer_agent.rb +251 -0
  46. data/lib/aspera/cli/version.rb +5 -0
  47. data/lib/aspera/colors.rb +39 -0
  48. data/lib/aspera/command_line_builder.rb +137 -0
  49. data/lib/aspera/fasp/aoc.rb +24 -0
  50. data/lib/aspera/fasp/connect.rb +99 -0
  51. data/lib/aspera/fasp/error.rb +21 -0
  52. data/lib/aspera/fasp/error_info.rb +60 -0
  53. data/lib/aspera/fasp/http_gw.rb +81 -0
  54. data/lib/aspera/fasp/installation.rb +240 -0
  55. data/lib/aspera/fasp/listener.rb +11 -0
  56. data/lib/aspera/fasp/local.rb +377 -0
  57. data/lib/aspera/fasp/manager.rb +69 -0
  58. data/lib/aspera/fasp/node.rb +88 -0
  59. data/lib/aspera/fasp/parameters.rb +235 -0
  60. data/lib/aspera/fasp/resume_policy.rb +76 -0
  61. data/lib/aspera/fasp/uri.rb +51 -0
  62. data/lib/aspera/faspex_gw.rb +196 -0
  63. data/lib/aspera/hash_ext.rb +28 -0
  64. data/lib/aspera/log.rb +80 -0
  65. data/lib/aspera/nagios.rb +71 -0
  66. data/lib/aspera/node.rb +14 -0
  67. data/lib/aspera/oauth.rb +319 -0
  68. data/lib/aspera/on_cloud.rb +421 -0
  69. data/lib/aspera/open_application.rb +72 -0
  70. data/lib/aspera/persistency_action_once.rb +42 -0
  71. data/lib/aspera/persistency_folder.rb +91 -0
  72. data/lib/aspera/preview/file_types.rb +300 -0
  73. data/lib/aspera/preview/generator.rb +258 -0
  74. data/lib/aspera/preview/image_error.png +0 -0
  75. data/lib/aspera/preview/options.rb +35 -0
  76. data/lib/aspera/preview/utils.rb +131 -0
  77. data/lib/aspera/preview/video_error.png +0 -0
  78. data/lib/aspera/proxy_auto_config.erb.js +287 -0
  79. data/lib/aspera/proxy_auto_config.rb +34 -0
  80. data/lib/aspera/rest.rb +296 -0
  81. data/lib/aspera/rest_call_error.rb +13 -0
  82. data/lib/aspera/rest_error_analyzer.rb +98 -0
  83. data/lib/aspera/rest_errors_aspera.rb +58 -0
  84. data/lib/aspera/ssh.rb +53 -0
  85. data/lib/aspera/sync.rb +82 -0
  86. data/lib/aspera/temp_file_manager.rb +37 -0
  87. data/lib/aspera/uri_reader.rb +25 -0
  88. metadata +288 -0
@@ -0,0 +1,34 @@
1
+ require 'uri'
2
+ require 'resolv'
3
+ require 'erb'
4
+
5
+ module Aspera
6
+ # evaluate a proxy autoconfig script
7
+ class ProxyAutoConfig
8
+ # template file is read once, it contains functions that can be used in a proxy autoconf script
9
+ PAC_FUNC_TEMPLATE=File.read(__FILE__.gsub(/\.rb$/,'.erb.js'))
10
+ private_constant :PAC_FUNC_TEMPLATE
11
+ # @param proxy_auto_config the proxy auto config script to be evaluated
12
+ def initialize(proxy_auto_config)
13
+ @proxy_auto_config=proxy_auto_config
14
+ end
15
+
16
+ # execut proxy auto config script for the given URL
17
+ def get_proxy(service_url)
18
+ # require at runtime, in case there is no js engine
19
+ require 'execjs'
20
+ # variables starting with "context_" are replaced in the ERB template file
21
+ # I did not find an easy way for the javascript to callback ruby
22
+ # and anyway, it only needs to get DNS translation
23
+ context_self='127.0.0.1'
24
+ context_host=URI.parse(service_url).host
25
+ context_ip=nil
26
+ Resolv::DNS.open{|dns|dns.each_address(context_host){|r_addr|context_ip=r_addr.to_s if r_addr.is_a?(Resolv::IPv4)}}
27
+ raise "DNS name not found: #{context_host}" if context_ip.nil?
28
+ pac_functions=ERB.new(PAC_FUNC_TEMPLATE).result(binding)
29
+ context = ExecJS.compile(pac_functions+@proxy_auto_config)
30
+ return context.call("FindProxyForURL", service_url, context_host)
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,296 @@
1
+ require 'aspera/log'
2
+ require 'aspera/oauth'
3
+ require 'aspera/rest_error_analyzer'
4
+ require 'aspera/hash_ext'
5
+ require 'aspera/rest_errors_aspera'
6
+ require 'net/http'
7
+ require 'net/https'
8
+ require 'json'
9
+ require 'base64'
10
+
11
+ # add cancel method to http
12
+ class Net::HTTP::Cancel < Net::HTTPRequest
13
+ METHOD = 'CANCEL'
14
+ REQUEST_HAS_BODY = false
15
+ RESPONSE_HAS_BODY = false
16
+ end
17
+
18
+ #class Net::HTTP::Delete < Net::HTTPRequest
19
+ # METHOD = 'DELETE'
20
+ # REQUEST_HAS_BODY = false
21
+ # RESPONSE_HAS_BODY = false
22
+ #end
23
+
24
+ module Aspera
25
+ # a simple class to make HTTP calls, equivalent to rest-client
26
+ # rest call errors are raised as exception RestCallError
27
+ # and error are analyzed in RestErrorAnalyzer
28
+ class Rest
29
+ private
30
+ # create and start keep alive connection on demand
31
+ def http_session
32
+ if @http_session.nil?
33
+ uri=self.class.build_uri(@params[:base_url])
34
+ # this honors http_proxy env var
35
+ @http_session=Net::HTTP.new(uri.host, uri.port)
36
+ @http_session.use_ssl = uri.scheme.eql?('https')
37
+ Log.log.debug("insecure=#{@@insecure}")
38
+ @http_session.verify_mode = OpenSSL::SSL::VERIFY_NONE if @@insecure
39
+ @http_session.set_debug_output($stdout) if @@debug
40
+ if @params.has_key?(:session_cb)
41
+ @params[:session_cb].call(@http_session)
42
+ end
43
+ # manually start session for keep alive (if supported by server, else, session is closed every time)
44
+ @http_session.start
45
+ end
46
+ return @http_session
47
+ end
48
+
49
+ # set to true enables debug in HTTP class
50
+ @@debug=false
51
+ # true if https ignore certificate
52
+ @@insecure=false
53
+ @@user_agent='Ruby'
54
+
55
+ public
56
+
57
+ def self.insecure=(v); @@insecure=v;Log.log.debug("insecure => #{@@insecure}".red);end
58
+
59
+ def self.insecure; @@insecure;end
60
+
61
+ def self.user_agent=(v); @@user_agent=v;Log.log.debug("user_agent => #{@@user_agent}".red);end
62
+
63
+ def self.user_agent; @@user_agent;end
64
+
65
+ def self.debug=(flag); @@debug=flag; Log.log.debug("debug http => #{flag}"); end
66
+
67
+ def self.basic_creds(user,pass); return "Basic #{Base64.strict_encode64("#{user}:#{pass}")}";end
68
+
69
+ attr_reader :params
70
+
71
+ # @param a_rest_params default call parameters and authentication (:auth) :
72
+ # :type (:basic, :oauth2, :url)
73
+ # :username [:basic]
74
+ # :password [:basic]
75
+ # :url_creds [:url]
76
+ # :session_cb a lambda which takes @http_session as arg, use this to change parameters
77
+ # :* [:oauth2] see Oauth class
78
+ def initialize(a_rest_params)
79
+ raise "ERROR: expecting Hash" unless a_rest_params.is_a?(Hash)
80
+ raise "ERROR: expecting base_url" unless a_rest_params[:base_url].is_a?(String)
81
+ @params=a_rest_params.clone
82
+ Log.dump('REST params',@params)
83
+ # base url without trailing slashes (note: string may be frozen)
84
+ @params[:base_url]=@params[:base_url].gsub(/\/+$/,'')
85
+ @http_session=nil
86
+ # default is no auth
87
+ @params[:auth]||={:type=>:none}
88
+ @params[:not_auth_codes]||=['401']
89
+ # translate old auth parameters, remove prefix, place in auth
90
+ [:auth,:basic,:oauth].each do |p_sym|
91
+ p_str=p_sym.to_s+'_'
92
+ @params.keys.select{|k|k.to_s.start_with?(p_str)}.each do |k_sym|
93
+ name=k_sym.to_s[p_str.length..-1]
94
+ name='grant' if k_sym.eql?(:oauth_type)
95
+ @params[:auth][name.to_sym]=@params[k_sym]
96
+ @params.delete(k_sym)
97
+ end
98
+ end
99
+ @oauth=Oauth.new(@params[:auth]) if @params[:auth][:type].eql?(:oauth2)
100
+ Log.dump('REST params(2)',@params)
101
+ end
102
+
103
+ def oauth_token(options={})
104
+ raise "ERROR: not Oauth" unless @oauth.is_a?(Oauth)
105
+ return @oauth.get_authorization(options)
106
+ end
107
+
108
+ # build URI from URL and parameters and check it is http or https
109
+ def self.build_uri(url,params=nil)
110
+ uri=URI.parse(url)
111
+ raise "REST endpoint shall be http(s)" unless ['http','https'].include?(uri.scheme)
112
+ if !params.nil?
113
+ # support array url params, there is no standard. Either p[]=1&p[]=2, or p=1&p=2
114
+ if params.is_a?(Hash)
115
+ orig=params
116
+ params=[]
117
+ orig.each do |k,v|
118
+ case v
119
+ when Array
120
+ suffix=v.first.eql?('[]') ? v.shift : ''
121
+ v.each do |e|
122
+ params.push([k+suffix,e])
123
+ end
124
+ else
125
+ params.push([k,v])
126
+ end
127
+ end
128
+ end
129
+ # CGI.unescape to transform back %5D into []
130
+ uri.query=CGI.unescape(URI.encode_www_form(params))
131
+ end
132
+ return uri
133
+ end
134
+
135
+ # HTTP/S REST call
136
+ # call_data has keys:
137
+ # :auth
138
+ # :operation
139
+ # :subpath
140
+ # :headers
141
+ # :json_params
142
+ # :url_params
143
+ # :www_body_params
144
+ # :text_body_params
145
+ # :save_to_file (filepath)
146
+ # :return_error (bool)
147
+ def call(call_data)
148
+ raise "Hash call parameter is required (#{call_data.class})" unless call_data.is_a?(Hash)
149
+ Log.log.debug("accessing #{call_data[:subpath]}".red.bold.bg_green)
150
+ call_data[:headers]||={}
151
+ call_data[:headers]['User-Agent'] ||= @@user_agent
152
+ call_data=@params.deep_merge(call_data)
153
+ case call_data[:auth][:type]
154
+ when :none
155
+ # no auth
156
+ when :basic
157
+ Log.log.debug("using Basic auth")
158
+ basic_auth_data=[call_data[:auth][:username],call_data[:auth][:password]]
159
+ when :oauth2
160
+ call_data[:headers]['Authorization']=oauth_token unless call_data[:headers].has_key?('Authorization')
161
+ when :url
162
+ call_data[:url_params]||={}
163
+ call_data[:auth][:url_creds].each do |key, value|
164
+ call_data[:url_params][key]=value
165
+ end
166
+ else raise "unsupported auth type: [#{call_data[:auth][:type]}]"
167
+ end
168
+ # TODO: shall we percent encode subpath (spaces) test with access key delete with space in id
169
+ # URI.escape()
170
+ uri=self.class.build_uri("#{@params[:base_url]}/#{call_data[:subpath]}",call_data[:url_params])
171
+ Log.log.debug("URI=#{uri}")
172
+ begin
173
+ # instanciate request object based on string name
174
+ req=Object::const_get('Net::HTTP::'+call_data[:operation].capitalize).new(uri.request_uri)
175
+ rescue NameError => e
176
+ raise "unsupported operation : #{call_data[:operation]}"
177
+ end
178
+ if call_data.has_key?(:json_params) and !call_data[:json_params].nil? then
179
+ req.body=JSON.generate(call_data[:json_params])
180
+ Log.dump('body JSON data',call_data[:json_params])
181
+ #Log.log.debug("body JSON data=#{JSON.pretty_generate(call_data[:json_params])}")
182
+ req['Content-Type'] = 'application/json'
183
+ #call_data[:headers]['Accept']='application/json'
184
+ end
185
+ if call_data.has_key?(:www_body_params) then
186
+ req.body=URI.encode_www_form(call_data[:www_body_params])
187
+ Log.log.debug("body www data=#{req.body.chomp}")
188
+ req['Content-Type'] = 'application/x-www-form-urlencoded'
189
+ end
190
+ if call_data.has_key?(:text_body_params) then
191
+ req.body=call_data[:text_body_params]
192
+ Log.log.debug("body data=#{req.body.chomp}")
193
+ end
194
+ # set headers
195
+ if call_data.has_key?(:headers) then
196
+ call_data[:headers].keys.each do |key|
197
+ req[key] = call_data[:headers][key]
198
+ end
199
+ end
200
+ # :type = :basic
201
+ req.basic_auth(*basic_auth_data) unless basic_auth_data.nil?
202
+
203
+ Log.log.debug("call_data = #{call_data}")
204
+ result={:http=>nil}
205
+ begin
206
+ # we try the call, and will retry only if oauth, as we can, first with refresh, and then re-auth if refresh is bad
207
+ oauth_tries ||= 2
208
+ Log.log.debug("send request")
209
+ http_session.request(req) do |response|
210
+ result[:http] = response
211
+ if call_data.has_key?(:save_to_file)
212
+ require 'ruby-progressbar'
213
+ total_size=result[:http]['Content-Length'].to_i
214
+ progress=ProgressBar.create(
215
+ :format => '%a %B %p%% %r KB/sec %e',
216
+ :rate_scale => lambda{|rate|rate/1024},
217
+ :title => 'progress',
218
+ :total => total_size)
219
+ Log.log.debug("before write file")
220
+ target_file=call_data[:save_to_file]
221
+ if !response['Content-Disposition'].nil? and m=response['Content-Disposition'].match(/filename="([^"]+)"/)
222
+ target_file=m[1]
223
+ end
224
+ Log.log.debug("saving to: #{target_file}")
225
+ File.open(target_file, "wb") do |file|
226
+ result[:http].read_body do |fragment|
227
+ file.write(fragment)
228
+ new_process=progress.progress+fragment.length
229
+ new_process = total_size if new_process > total_size
230
+ progress.progress=new_process
231
+ end
232
+ end
233
+ progress=nil
234
+ end
235
+ end
236
+ # sometimes there is a ITF8 char (e.g. (c) )
237
+ result[:http].body.force_encoding("UTF-8") if result[:http].body.is_a?(String)
238
+ Log.log.debug("result: body=#{result[:http].body}")
239
+ result_mime=(result[:http]['Content-Type']||'text/plain').split(';').first
240
+ case result_mime
241
+ when 'application/json','application/vnd.api+json'
242
+ result[:data]=JSON.parse(result[:http].body) rescue nil
243
+ else #when 'text/plain'
244
+ result[:data]=result[:http].body
245
+ end
246
+ Log.dump("result: parsed: #{result_mime}",result[:data])
247
+ Log.log.debug("result: code=#{result[:http].code}")
248
+ RestErrorAnalyzer.instance.raiseOnError(req,result)
249
+ rescue RestCallError => e
250
+ # not authorized: oauth token expired
251
+ if @params[:not_auth_codes].include?(result[:http].code.to_s) and call_data[:auth][:type].eql?(:oauth2)
252
+ begin
253
+ # try to use refresh token
254
+ req['Authorization']=oauth_token(refresh: true)
255
+ rescue RestCallError => e
256
+ Log.log.error("refresh failed".bg_red)
257
+ # regenerate a brand new token
258
+ req['Authorization']=oauth_token
259
+ end
260
+ Log.log.debug("using new token=#{call_data[:headers]['Authorization']}")
261
+ retry unless (oauth_tries -= 1).zero?
262
+ end # if
263
+ # raise exception if could not retry and not return error in result
264
+ raise e unless call_data[:return_error]
265
+ end
266
+ Log.log.debug("result=#{result}")
267
+ return result
268
+
269
+ end
270
+
271
+ #
272
+ # CRUD methods here
273
+ #
274
+
275
+ # @param encoding : one of: :json_params, :url_params
276
+ def create(subpath,params,encoding=:json_params)
277
+ return call({:operation=>'POST',:subpath=>subpath,:headers=>{'Accept'=>'application/json'},encoding=>params})
278
+ end
279
+
280
+ def read(subpath,args=nil)
281
+ return call({:operation=>'GET',:subpath=>subpath,:headers=>{'Accept'=>'application/json'},:url_params=>args})
282
+ end
283
+
284
+ def update(subpath,params)
285
+ return call({:operation=>'PUT',:subpath=>subpath,:headers=>{'Accept'=>'application/json'},:json_params=>params})
286
+ end
287
+
288
+ def delete(subpath)
289
+ return call({:operation=>'DELETE',:subpath=>subpath,:headers=>{'Accept'=>'application/json'}})
290
+ end
291
+
292
+ def cancel(subpath)
293
+ return call({:operation=>'CANCEL',:subpath=>subpath,:headers=>{'Accept'=>'application/json'}})
294
+ end
295
+ end
296
+ end #module Aspera
@@ -0,0 +1,13 @@
1
+ module Aspera
2
+ # raised on error after REST call
3
+ class RestCallError < StandardError
4
+ attr_accessor :request
5
+ attr_accessor :response
6
+ # @param http response
7
+ def initialize(req,resp,msg)
8
+ @request = req
9
+ @response = resp
10
+ super(msg)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,98 @@
1
+ require 'aspera/log'
2
+ require 'aspera/rest_call_error'
3
+ require 'singleton'
4
+
5
+ module Aspera
6
+ # analyze error codes returned by REST calls and raise ruby exception
7
+ class RestErrorAnalyzer
8
+ include Singleton
9
+ # the singleton object is registered with application specific handlers
10
+ def initialize
11
+ # list of handlers
12
+ @error_handlers=[]
13
+ self.add_handler('Type Generic') do |type,context|
14
+ if !context[:response].code.start_with?('2')
15
+ # add generic information
16
+ RestErrorAnalyzer.add_error(context,type,"#{context[:request]['host']} #{context[:response].code} #{context[:response].message}")
17
+ end
18
+ end
19
+ end
20
+
21
+ # Use this method to analyze a EST result and raise an exception
22
+ # Analyzes REST call response and raises a RestCallError exception
23
+ # if HTTP result code is not 2XX
24
+ def raiseOnError(req,res)
25
+ context={
26
+ messages: [],
27
+ request: req,
28
+ response: res[:http],
29
+ data: res[:data]
30
+ }
31
+ # multiple error messages can be found
32
+ # analyze errors from provided handlers
33
+ # note that there can be an error even if code is 2XX
34
+ @error_handlers.each do |handler|
35
+ begin
36
+ #Log.log.debug("test exception: #{handler[:name]}")
37
+ handler[:block].call(handler[:name],context)
38
+ rescue => e
39
+ Log.log.error("ERROR in handler:\n#{e.message}\n#{e.backtrace}")
40
+ end
41
+ end
42
+ unless context[:messages].empty?
43
+ raise RestCallError.new(context[:request],context[:response],context[:messages].join("\n"))
44
+ end
45
+ end
46
+
47
+ # add a new error handler (done at application initialisation)
48
+ # @param name : name of error handler (for logs)
49
+ # @param block : processing of response: takes two parameters: name, context
50
+ # name is the one provided here
51
+ # context is built in method raiseOnError
52
+ def add_handler(name,&block)
53
+ @error_handlers.unshift({name: name, block: block})
54
+ end
55
+
56
+ # add a simple error handler
57
+ # check that key exists and is string under specified path (hash)
58
+ # adds other keys as secondary information
59
+ def add_simple_handler(name,*args)
60
+ add_handler(name) do |type,context|
61
+ # need to clone because we modify and same array is used subsequently
62
+ path=args.clone
63
+ #Log.log.debug("path=#{path}")
64
+ # if last in path is boolean it tells if the error is only with http error code or always
65
+ always=[true, false].include?(path.last) ? path.pop : false
66
+ if context[:data].is_a?(Hash) and (!context[:response].code.start_with?('2') or always)
67
+ msg_key=path.pop
68
+ # dig and find sub entry corresponding to path in deep hash
69
+ error_struct=path.inject(context[:data]) { |subhash, key| subhash.respond_to?(:keys) ? subhash[key] : nil }
70
+ if error_struct.is_a?(Hash) and error_struct[msg_key].is_a?(String)
71
+ RestErrorAnalyzer.add_error(context,type,error_struct[msg_key])
72
+ error_struct.each do |k,v|
73
+ next if k.eql?(msg_key)
74
+ RestErrorAnalyzer.add_error(context,"#{type}(sub)","#{k}: #{v}") if [String,Integer].include?(v.class)
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end # add_simple_handler
80
+
81
+ # used by handler to add an error description to list of errors
82
+ # for logging and tracing : collect error descriptions (create file to activate)
83
+ # @param context a Hash containing the result context, provided to handler
84
+ # @param type a string describing type of exception, for logging purpose
85
+ # @param msg one error message to add to list
86
+ def self.add_error(context,type,msg)
87
+ context[:messages].push(msg)
88
+ # log error for further analysis (file must exist to activate)
89
+ exc_log_file=File.join(Fasp::Installation.instance.config_folder,'exceptions.log')
90
+ if File.exist?(exc_log_file)
91
+ File.open(exc_log_file,'a+') do |f|
92
+ f.write("\n=#{type}=====\n#{context[:request].method} #{context[:request].path}\n#{context[:response].code}\n#{JSON.generate(context[:data])}\n#{context[:messages].join("\n")}")
93
+ end
94
+ end
95
+ end
96
+
97
+ end
98
+ end
@@ -0,0 +1,58 @@
1
+ require 'aspera/rest_error_analyzer'
2
+ require 'aspera/log'
3
+
4
+ module Aspera
5
+ # REST error handlers for various Aspera REST APIs
6
+ class RestErrorsAspera
7
+ # handlers should probably be defined by plugins for modularity
8
+ def self.registerHandlers
9
+ Log.log.debug("registering Aspera REST error handlers")
10
+ # Faspex 4: both user_message and internal_message, and code 200
11
+ # example: missing meta data on package creation
12
+ RestErrorAnalyzer.instance.add_simple_handler('Type 1: error:user_message','error','user_message',true)
13
+ RestErrorAnalyzer.instance.add_simple_handler('Type 2: error:description','error','description')
14
+ RestErrorAnalyzer.instance.add_simple_handler('Type 3: error:internal_message','error','internal_message')
15
+ # AoC Automation
16
+ RestErrorAnalyzer.instance.add_simple_handler('AoC Automation','error')
17
+ RestErrorAnalyzer.instance.add_simple_handler('Type 5','error_description')
18
+ RestErrorAnalyzer.instance.add_simple_handler('Type 6','message')
19
+ RestErrorAnalyzer.instance.add_handler('Type 7: errors[]') do |name,context|
20
+ if context[:data].is_a?(Hash) and context[:data]['errors'].is_a?(Hash)
21
+ context[:data]['errors'].each do |k,v|
22
+ RestErrorAnalyzer.add_error(context,name,"#{k}: #{v}")
23
+ end
24
+ end
25
+ end
26
+ # call to upload_setup and download_setup of node api
27
+ RestErrorAnalyzer.instance.add_handler('T8:node: *_setup') do |type,context|
28
+ if context[:data].is_a?(Hash)
29
+ d_t_s=context[:data]['transfer_specs']
30
+ if d_t_s.is_a?(Array)
31
+ d_t_s.each do |res|
32
+ #r_err=res['transfer_spec']['error']
33
+ r_err=res['error']
34
+ if r_err.is_a?(Hash)
35
+ RestErrorAnalyzer.add_error(context,type,"#{r_err['code']}: #{r_err['reason']}: #{r_err['user_message']}")
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ RestErrorAnalyzer.instance.add_simple_handler('T9:IBM cloud IAM','errorMessage')
42
+ RestErrorAnalyzer.instance.add_simple_handler('T10:faspex v4','user_message')
43
+ RestErrorAnalyzer.instance.add_handler('bss graphql') do |type,context|
44
+ if context[:data].is_a?(Hash)
45
+ d_t_s=context[:data]['errors']
46
+ if d_t_s.is_a?(Array)
47
+ d_t_s.each do |res|
48
+ r_err=res['message']
49
+ if r_err.is_a?(String)
50
+ RestErrorAnalyzer.add_error(context,type,r_err)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end # registerErrorTypes
57
+ end
58
+ end