aspera-cli 4.25.2 → 4.25.4
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +430 -406
- data/CONTRIBUTING.md +104 -93
- data/README.md +6 -3
- data/lib/aspera/api/aoc.rb +15 -11
- data/lib/aspera/api/cos_node.rb +4 -0
- data/lib/aspera/api/faspex.rb +35 -7
- data/lib/aspera/api/node.rb +81 -27
- data/lib/aspera/assert.rb +1 -1
- data/lib/aspera/cli/formatter.rb +27 -11
- data/lib/aspera/cli/hints.rb +7 -0
- data/lib/aspera/cli/manager.rb +51 -30
- data/lib/aspera/cli/plugins/aoc.rb +152 -123
- data/lib/aspera/cli/plugins/base.rb +16 -19
- data/lib/aspera/cli/plugins/config.rb +6 -44
- data/lib/aspera/cli/plugins/faspex.rb +4 -4
- data/lib/aspera/cli/plugins/faspex5.rb +92 -83
- data/lib/aspera/cli/plugins/node.rb +10 -15
- data/lib/aspera/cli/plugins/oauth.rb +26 -25
- data/lib/aspera/cli/plugins/preview.rb +3 -3
- data/lib/aspera/cli/plugins/shares.rb +15 -7
- data/lib/aspera/cli/special_values.rb +1 -0
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +2 -1
- data/lib/aspera/colors.rb +7 -0
- data/lib/aspera/faspex_gw.rb +5 -5
- data/lib/aspera/faspex_postproc.rb +4 -4
- data/lib/aspera/log.rb +12 -11
- data/lib/aspera/markdown.rb +5 -0
- data/lib/aspera/node_simulator.rb +1 -1
- data/lib/aspera/oauth/base.rb +1 -1
- data/lib/aspera/oauth/url_json.rb +2 -2
- data/lib/aspera/rest.rb +68 -48
- data/lib/aspera/rest_error_analyzer.rb +38 -36
- data/lib/aspera/rest_errors_aspera.rb +19 -18
- data/lib/aspera/transfer/spec.rb +1 -0
- data.tar.gz.sig +0 -0
- metadata +2 -2
- metadata.gz.sig +0 -0
data/lib/aspera/log.rb
CHANGED
|
@@ -65,11 +65,8 @@ module Aspera
|
|
|
65
65
|
|
|
66
66
|
# Class methods
|
|
67
67
|
class << self
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
# @param colors [Array(Symbol)] List of decorations
|
|
71
|
-
def apply_colors(value, colors)
|
|
72
|
-
colors.inject(value){ |s, c| s.send(c)}
|
|
68
|
+
def short_levl(level)
|
|
69
|
+
"#{level[0, 3]}#{level[-1]}"
|
|
73
70
|
end
|
|
74
71
|
|
|
75
72
|
# Get the logger object of singleton
|
|
@@ -154,8 +151,8 @@ module Aspera
|
|
|
154
151
|
|
|
155
152
|
def formatter=(formatter)
|
|
156
153
|
if formatter.is_a?(String)
|
|
157
|
-
raise Error, "Unknown formatter #{formatter}, use one of: #{FORMATTERS.
|
|
158
|
-
formatter =
|
|
154
|
+
raise Error, "Unknown formatter #{formatter}, use one of: #{FORMATTERS.join(', ')}" unless FORMATTER_LAMBDAS.key?(formatter.to_sym)
|
|
155
|
+
formatter = FORMATTER_LAMBDAS[formatter.to_sym]
|
|
159
156
|
elsif !formatter.respond_to?(:call) && !formatter.is_a?(Logger::Formatter)
|
|
160
157
|
raise Error, 'Formatter must be a String, a Logger::Formatter or a Proc'
|
|
161
158
|
end
|
|
@@ -226,18 +223,22 @@ module Aspera
|
|
|
226
223
|
UNKNOWN: %i{blink}
|
|
227
224
|
}.freeze
|
|
228
225
|
|
|
229
|
-
# Short levels with color
|
|
230
|
-
LVL_COLOR = LVL_DECO.
|
|
226
|
+
# Short (4-letters) levels with color
|
|
227
|
+
LVL_COLOR = LVL_DECO.to_h do |k, v|
|
|
228
|
+
[k, short_levl(k).apply(*v)]
|
|
229
|
+
end.freeze
|
|
231
230
|
|
|
232
231
|
DEFAULT_FORMATTER = ->(s, _d, _p, m){"#{LVL_COLOR[s]} #{m}\n"}
|
|
233
232
|
|
|
234
233
|
# pre-defined formatters
|
|
235
|
-
|
|
234
|
+
FORMATTER_LAMBDAS = {
|
|
236
235
|
standard: Logger::Formatter.new,
|
|
237
236
|
default: DEFAULT_FORMATTER,
|
|
238
237
|
caller: ->(s, _d, _p, m){"#{LVL_COLOR[s]} #{Log.caller_method}\n#{m}\n"}
|
|
239
238
|
}.freeze
|
|
240
239
|
|
|
241
|
-
|
|
240
|
+
FORMATTERS = FORMATTER_LAMBDAS.keys
|
|
241
|
+
|
|
242
|
+
private_constant :LVL_DECO, :DEFAULT_FORMATTER, :FORMATTER_LAMBDAS
|
|
242
243
|
end
|
|
243
244
|
end
|
data/lib/aspera/markdown.rb
CHANGED
|
@@ -328,7 +328,7 @@ module Aspera
|
|
|
328
328
|
|
|
329
329
|
def set_json_response(request, response, json, code: 200)
|
|
330
330
|
response.status = code
|
|
331
|
-
response['Content-Type'] =
|
|
331
|
+
response['Content-Type'] = Mime::JSON
|
|
332
332
|
response.body = json.to_json
|
|
333
333
|
Log.log.trace1{Log.obj_dump("response for #{request.request_method} #{request.path}", json)}
|
|
334
334
|
end
|
data/lib/aspera/oauth/base.rb
CHANGED
|
@@ -53,7 +53,7 @@ module Aspera
|
|
|
53
53
|
def create_token_call(creation_params)
|
|
54
54
|
Log.log.debug{'Generating a new token'.bg_green}
|
|
55
55
|
return @api.create(@path_token, nil, query: creation_params, ret: :resp) if @use_query
|
|
56
|
-
return @api.create(@path_token, creation_params, content_type:
|
|
56
|
+
return @api.create(@path_token, creation_params, content_type: Mime::WWW, ret: :resp)
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
# Create base parameters for token creation calls
|
|
@@ -24,9 +24,9 @@ module Aspera
|
|
|
24
24
|
operation: 'POST',
|
|
25
25
|
subpath: path_token,
|
|
26
26
|
query: @query.merge(scope: params[:scope]), # scope is here because it may change over time (node)
|
|
27
|
-
content_type:
|
|
27
|
+
content_type: Mime::JSON,
|
|
28
28
|
body: @body,
|
|
29
|
-
headers: {'Accept' =>
|
|
29
|
+
headers: {'Accept' => Mime::JSON},
|
|
30
30
|
ret: :resp
|
|
31
31
|
)
|
|
32
32
|
end
|
data/lib/aspera/rest.rb
CHANGED
|
@@ -33,7 +33,7 @@ module Aspera
|
|
|
33
33
|
class RestParameters
|
|
34
34
|
include Singleton
|
|
35
35
|
|
|
36
|
-
attr_accessor :user_agent, :download_partial_suffix, :retry_on_error, :retry_on_timeout, :retry_on_unavailable, :retry_max, :retry_sleep, :session_cb, :progress_bar
|
|
36
|
+
attr_accessor :user_agent, :download_partial_suffix, :retry_on_error, :retry_on_timeout, :retry_on_unavailable, :retry_max, :retry_sleep, :session_cb, :progress_bar, :spinner_cb
|
|
37
37
|
|
|
38
38
|
private
|
|
39
39
|
|
|
@@ -47,20 +47,31 @@ module Aspera
|
|
|
47
47
|
@retry_sleep = 4
|
|
48
48
|
@session_cb = nil
|
|
49
49
|
@progress_bar = nil
|
|
50
|
+
@spinner_cb = nil
|
|
50
51
|
end
|
|
51
52
|
end
|
|
52
53
|
|
|
53
54
|
class EntityNotFound < Error
|
|
54
55
|
end
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
module Mime
|
|
58
|
+
JSON = 'application/json'
|
|
59
|
+
WWW = 'application/x-www-form-urlencoded'
|
|
60
|
+
TEXT = 'text/plain'
|
|
61
|
+
# Check if a MIME type is JSON, including parameters, e.g. application/json; charset=utf-8
|
|
62
|
+
def json?(mime)
|
|
63
|
+
JSON_LIST.include?(mime)
|
|
64
|
+
end
|
|
65
|
+
module_function :json?
|
|
66
|
+
# Content-Type that are JSON
|
|
67
|
+
JSON_LIST = [JSON, 'application/vnd.api+json', 'application/x-javascript'].freeze
|
|
68
|
+
private_constant :JSON_LIST
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Make HTTP calls, equivalent to rest-client
|
|
57
72
|
# rest call errors are raised as exception RestCallError
|
|
58
73
|
# and error are analyzed in RestErrorAnalyzer
|
|
59
74
|
class Rest
|
|
60
|
-
MIME_JSON = 'application/json'
|
|
61
|
-
MIME_WWW = 'application/x-www-form-urlencoded'
|
|
62
|
-
MIME_TEXT = 'text/plain'
|
|
63
|
-
|
|
64
75
|
# Special query parameter: max number of items for list command
|
|
65
76
|
MAX_ITEMS = 'max'
|
|
66
77
|
# Special query parameter: max number of pages for list command
|
|
@@ -78,8 +89,9 @@ module Aspera
|
|
|
78
89
|
query
|
|
79
90
|
end
|
|
80
91
|
|
|
81
|
-
# Build URI from URL and parameters and check it is http or https
|
|
82
|
-
# Check
|
|
92
|
+
# Build URI from URL and parameters and check it is `http` or `https`.
|
|
93
|
+
# Check if php style is specified.
|
|
94
|
+
# `nil` values in query result in key without value, e.g. `?a`, while empty string values result in `?a=`.
|
|
83
95
|
# @param url [String] The URL without query.
|
|
84
96
|
# @param query [Hash,Array,String] The query.
|
|
85
97
|
def build_uri(url, query)
|
|
@@ -95,18 +107,19 @@ module Aspera
|
|
|
95
107
|
URI.encode_www_form(h_to_query_array(query))
|
|
96
108
|
when Array
|
|
97
109
|
Aspera.assert(query.all?{ |i| i.is_a?(Array) && i.length.eql?(2)}){'Query must be array of arrays of 2 elements'}
|
|
98
|
-
URI.encode_www_form(query)
|
|
110
|
+
URI.encode_www_form(query) # remove nil values
|
|
99
111
|
else Aspera.error_unexpected_value(query.class){'query type'}
|
|
100
112
|
end.gsub('%5B%5D=', '[]=')
|
|
101
113
|
# [] is allowed in url parameters
|
|
102
114
|
uri
|
|
103
115
|
end
|
|
104
116
|
|
|
117
|
+
# Support array for query parameter, there is no standard.
|
|
118
|
+
# Either p=1&p=2 (default)
|
|
119
|
+
# or p[]=1&p[]=2 (if `:x_array_php_style` is set to true in query)
|
|
105
120
|
# @param query [Hash] HTTP query as hash
|
|
106
121
|
def h_to_query_array(query)
|
|
107
122
|
Aspera.assert_type(query, Hash)
|
|
108
|
-
# Support array for query parameter, there is no standard.
|
|
109
|
-
# Either p[]=1&p[]=2, or p=1&p=2
|
|
110
123
|
suffix = query.delete(:x_array_php_style) ? '[]' : nil
|
|
111
124
|
query.each_with_object([]) do |(k, v), query_array|
|
|
112
125
|
case v
|
|
@@ -143,8 +156,8 @@ module Aspera
|
|
|
143
156
|
end
|
|
144
157
|
|
|
145
158
|
# Start a HTTP/S session, also used for web sockets
|
|
146
|
-
# @param base_url [String]
|
|
147
|
-
# @return [Net::HTTP]
|
|
159
|
+
# @param base_url [String] Base url of HTTP/S session
|
|
160
|
+
# @return [Net::HTTP] A started HTTP session
|
|
148
161
|
def start_http_session(base_url)
|
|
149
162
|
uri = URI.parse(base_url)
|
|
150
163
|
Aspera.assert_values(uri.scheme, %w[http https]){'URI scheme'}
|
|
@@ -302,16 +315,16 @@ module Aspera
|
|
|
302
315
|
# HTTP/S REST call
|
|
303
316
|
# @param operation [String] HTTP operation (GET, POST, PUT, DELETE)
|
|
304
317
|
# @param subpath [String] subpath of REST API
|
|
305
|
-
# @param query [Hash] URL parameters
|
|
318
|
+
# @param query [Hash{String,Symbol => Object}] URL parameters
|
|
306
319
|
# @param content_type [String, nil] Type of body parameters (one of MIME_*) and serialization, else use headers
|
|
307
|
-
# @param body
|
|
308
|
-
# @param headers [Hash]
|
|
309
|
-
# @param save_to_file [String, nil]
|
|
310
|
-
# @param exception [Boolean]
|
|
311
|
-
# @param ret
|
|
312
|
-
# @return [(HTTPResponse
|
|
313
|
-
# @return [HTTPResponse]
|
|
314
|
-
# @return [Hash]
|
|
320
|
+
# @param body [Hash, String, nil] Body parameters
|
|
321
|
+
# @param headers [Hash{String => String}] Additional headers (override Content-Type)
|
|
322
|
+
# @param save_to_file [String, nil] File path to save response body
|
|
323
|
+
# @param exception [Boolean] Whether to raise an exception on HTTP error
|
|
324
|
+
# @param ret [Symbol] One of :data, :resp, :both — controls return value
|
|
325
|
+
# @return [Array(Hash, Net::HTTPResponse)] When `ret` is :both
|
|
326
|
+
# @return [Net::HTTPResponse] When `ret` is :resp
|
|
327
|
+
# @return [Hash] When `ret` is :data
|
|
315
328
|
# @raise [RestCallError] on error if `exception` is true
|
|
316
329
|
def call(
|
|
317
330
|
operation:,
|
|
@@ -373,15 +386,15 @@ module Aspera
|
|
|
373
386
|
end
|
|
374
387
|
case content_type
|
|
375
388
|
when nil # ignore
|
|
376
|
-
when
|
|
389
|
+
when Mime::JSON
|
|
377
390
|
req.body = JSON.generate(body) # , ascii_only: true
|
|
378
|
-
req['Content-Type'] =
|
|
379
|
-
when
|
|
391
|
+
req['Content-Type'] = Mime::JSON
|
|
392
|
+
when Mime::WWW
|
|
380
393
|
req.body = URI.encode_www_form(body)
|
|
381
|
-
req['Content-Type'] =
|
|
382
|
-
when
|
|
394
|
+
req['Content-Type'] = Mime::WWW
|
|
395
|
+
when Mime::TEXT
|
|
383
396
|
req.body = body
|
|
384
|
-
req['Content-Type'] =
|
|
397
|
+
req['Content-Type'] = Mime::TEXT
|
|
385
398
|
else Aspera.error_unexpected_value(content_type){'body type'}
|
|
386
399
|
end
|
|
387
400
|
# set headers
|
|
@@ -401,12 +414,12 @@ module Aspera
|
|
|
401
414
|
# make http request (pipelined)
|
|
402
415
|
http_session.request(req) do |response|
|
|
403
416
|
result_http = response
|
|
404
|
-
result_mime = self.class.parse_header(result_http['Content-Type'] ||
|
|
405
|
-
Log.log.debug{"response: code=#{result_http.code}, mime=#{result_mime},
|
|
417
|
+
result_mime = self.class.parse_header(result_http['Content-Type'] || Mime::TEXT)[:type]
|
|
418
|
+
Log.log.debug{"response: code=#{result_http.code}, mime=#{result_mime}, content-type=#{response['Content-Type']}"}
|
|
406
419
|
# JSON data needs to be parsed, in case it contains an error code
|
|
407
420
|
if !save_to_file.nil? &&
|
|
408
421
|
result_http.code.to_s.start_with?('2') &&
|
|
409
|
-
!
|
|
422
|
+
!Mime.json?(result_mime)
|
|
410
423
|
total_size = result_http['Content-Length']&.to_i
|
|
411
424
|
Log.log.debug('before write file')
|
|
412
425
|
target_file = save_to_file
|
|
@@ -439,16 +452,14 @@ module Aspera
|
|
|
439
452
|
end
|
|
440
453
|
end
|
|
441
454
|
Log.log.debug{"result: code=#{result_http.code} mime=#{result_mime}"}
|
|
442
|
-
# sometimes there is a UTF8 char (e.g.
|
|
455
|
+
# sometimes there is a UTF8 char (e.g. © )
|
|
456
|
+
# TODO : related to mime type encoding ?
|
|
443
457
|
# result_http.body.force_encoding('UTF-8') if result_http.body.is_a?(String)
|
|
444
458
|
# Log.log.debug{"result: body=#{result_http.body}"}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
else # when MIME_TEXT
|
|
450
|
-
result_data = result_http.body
|
|
451
|
-
end
|
|
459
|
+
result_data = result_http.body
|
|
460
|
+
Log.dump(:result_data_raw, result_data, level: :trace1)
|
|
461
|
+
result_data = JSON.parse(result_data) if Mime.json?(result_mime) && !result_data.nil? && !result_data.empty?
|
|
462
|
+
Log.dump(:result_data, result_data)
|
|
452
463
|
RestErrorAnalyzer.instance.raise_on_error(req, result_data, result_http)
|
|
453
464
|
unless file_saved || save_to_file.nil?
|
|
454
465
|
FileUtils.mkdir_p(File.dirname(save_to_file))
|
|
@@ -526,27 +537,39 @@ module Aspera
|
|
|
526
537
|
|
|
527
538
|
# Create: `POST`
|
|
528
539
|
def create(subpath, params, **kwargs)
|
|
529
|
-
|
|
540
|
+
kwargs[:headers] ||= {}
|
|
541
|
+
kwargs[:headers]['Accept'] = Mime::JSON unless kwargs[:headers].key?('Accept')
|
|
542
|
+
kwargs[:content_type] = Mime::JSON unless kwargs.key?(:content_type)
|
|
543
|
+
return call(operation: 'POST', subpath: subpath, body: params, **kwargs)
|
|
530
544
|
end
|
|
531
545
|
|
|
532
546
|
# Read: `GET`
|
|
533
547
|
def read(subpath, query = nil, **kwargs)
|
|
534
|
-
|
|
548
|
+
kwargs[:headers] ||= {}
|
|
549
|
+
kwargs[:headers]['Accept'] = Mime::JSON unless kwargs[:headers].key?('Accept')
|
|
550
|
+
return call(operation: 'GET', subpath: subpath, query: query, **kwargs)
|
|
535
551
|
end
|
|
536
552
|
|
|
537
553
|
# Update: `PUT`
|
|
538
554
|
def update(subpath, params, **kwargs)
|
|
539
|
-
|
|
555
|
+
kwargs[:headers] ||= {}
|
|
556
|
+
kwargs[:headers]['Accept'] = Mime::JSON unless kwargs[:headers].key?('Accept')
|
|
557
|
+
kwargs[:content_type] = Mime::JSON unless kwargs.key?(:content_type)
|
|
558
|
+
return call(operation: 'PUT', subpath: subpath, body: params, **kwargs)
|
|
540
559
|
end
|
|
541
560
|
|
|
542
561
|
# Delete: `DELETE`
|
|
543
562
|
def delete(subpath, params = nil, **kwargs)
|
|
544
|
-
|
|
563
|
+
kwargs[:headers] ||= {}
|
|
564
|
+
kwargs[:headers]['Accept'] = Mime::JSON unless kwargs[:headers].key?('Accept')
|
|
565
|
+
return call(operation: 'DELETE', subpath: subpath, query: params, **kwargs)
|
|
545
566
|
end
|
|
546
567
|
|
|
547
568
|
# Cancel: `CANCEL`
|
|
548
569
|
def cancel(subpath, **kwargs)
|
|
549
|
-
|
|
570
|
+
kwargs[:headers] ||= {}
|
|
571
|
+
kwargs[:headers]['Accept'] = Mime::JSON unless kwargs[:headers].key?('Accept')
|
|
572
|
+
return call(operation: 'CANCEL', subpath: subpath, **kwargs)
|
|
550
573
|
end
|
|
551
574
|
|
|
552
575
|
# Query entity by general search (read with parameter `q`)
|
|
@@ -577,11 +600,8 @@ module Aspera
|
|
|
577
600
|
end
|
|
578
601
|
end
|
|
579
602
|
|
|
580
|
-
# Content-Type that are JSON
|
|
581
|
-
JSON_DECODE = [MIME_JSON, 'application/vnd.api+json', 'application/x-javascript'].freeze
|
|
582
|
-
|
|
583
603
|
UNAVAILABLE_CODES = ['503']
|
|
584
604
|
|
|
585
|
-
private_constant :
|
|
605
|
+
private_constant :UNAVAILABLE_CODES
|
|
586
606
|
end
|
|
587
607
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require 'aspera/rest_call_error'
|
|
4
4
|
require 'aspera/log'
|
|
5
5
|
require 'singleton'
|
|
6
|
+
require 'net/http'
|
|
6
7
|
|
|
7
8
|
module Aspera
|
|
8
9
|
# analyze error codes returned by REST calls and raise ruby exception
|
|
@@ -16,10 +17,10 @@ module Aspera
|
|
|
16
17
|
# list of handlers
|
|
17
18
|
@error_handlers = []
|
|
18
19
|
@log_file = nil
|
|
19
|
-
add_handler('Type Generic') do |type,
|
|
20
|
-
if !
|
|
20
|
+
add_handler('Type Generic') do |type, context|
|
|
21
|
+
if !context[:response].code.start_with?('2')
|
|
21
22
|
# add generic information
|
|
22
|
-
RestErrorAnalyzer.add_error(
|
|
23
|
+
RestErrorAnalyzer.add_error(context, type, "#{context[:request]['host']} #{context[:response].code} #{context[:response].message}")
|
|
23
24
|
end
|
|
24
25
|
end
|
|
25
26
|
end
|
|
@@ -27,9 +28,12 @@ module Aspera
|
|
|
27
28
|
# Use this method to analyze a EST result and raise an exception
|
|
28
29
|
# Analyzes REST call response and raises a RestCallError exception
|
|
29
30
|
# if HTTP result code is not 2XX
|
|
31
|
+
# @param req [Net::HTTPRequest]
|
|
32
|
+
# @param data [Object]
|
|
33
|
+
# @param http [Net::HTTPResponse]
|
|
30
34
|
def raise_on_error(req, data, http)
|
|
31
35
|
Log.log.debug{"raise_on_error #{req.method} #{req.path} #{http.code}"}
|
|
32
|
-
|
|
36
|
+
context = {
|
|
33
37
|
messages: [],
|
|
34
38
|
request: req,
|
|
35
39
|
response: http,
|
|
@@ -39,44 +43,42 @@ module Aspera
|
|
|
39
43
|
# analyze errors from provided handlers
|
|
40
44
|
# note that there can be an error even if code is 2XX
|
|
41
45
|
@error_handlers.each do |handler|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
rescue StandardError => e
|
|
46
|
-
Log.log.error{"ERROR in handler:\n#{e.message}\n#{e.backtrace}"}
|
|
47
|
-
end
|
|
46
|
+
handler[:block].call(handler[:name], context)
|
|
47
|
+
rescue StandardError => e
|
|
48
|
+
Log.log.error{"ERROR in handler:\n#{e.message}\n#{e.backtrace}"}
|
|
48
49
|
end
|
|
49
|
-
raise RestCallError
|
|
50
|
+
raise RestCallError, context unless context[:messages].empty?
|
|
50
51
|
end
|
|
51
52
|
|
|
52
|
-
#
|
|
53
|
-
# @param name
|
|
54
|
-
# @param block
|
|
53
|
+
# Add a new error handler (done at application initialization)
|
|
54
|
+
# @param name [String] name of error handler (for logs)
|
|
55
|
+
# @param block [Proc] processing of response: takes two parameters: `name`, `context`
|
|
55
56
|
# name is the one provided here
|
|
56
|
-
#
|
|
57
|
+
# context is built in method raise_on_error
|
|
57
58
|
def add_handler(name, &block)
|
|
58
59
|
@error_handlers.unshift({name: name, block: block})
|
|
60
|
+
nil
|
|
59
61
|
end
|
|
60
62
|
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
# @param name
|
|
65
|
-
# @param always [
|
|
66
|
-
# @param path
|
|
63
|
+
# Add a simple error handler
|
|
64
|
+
# Check that key exists and is string under specified path (hash)
|
|
65
|
+
# Adds other keys as secondary information
|
|
66
|
+
# @param name [String] name of error handler (for logs)
|
|
67
|
+
# @param always [Boolean] if true, always add error message, even if response code is 2XX
|
|
68
|
+
# @param path [Array] path to error message in response
|
|
67
69
|
def add_simple_handler(name:, always: false, path:)
|
|
68
70
|
path.freeze
|
|
69
|
-
add_handler(name) do |type,
|
|
70
|
-
if
|
|
71
|
+
add_handler(name) do |type, context|
|
|
72
|
+
if context[:data].is_a?(Hash) && (!context[:response].code.start_with?('2') || always)
|
|
71
73
|
# Log.log.debug{"simple_handler: #{type} #{path} #{path.last}"}
|
|
72
74
|
# dig and find hash containing error message
|
|
73
|
-
error_struct = path.length.eql?(1) ?
|
|
75
|
+
error_struct = path.length.eql?(1) ? context[:data] : context[:data].dig(*path[0..-2])
|
|
74
76
|
# Log.log.debug{"found: #{error_struct.class} #{error_struct}"}
|
|
75
77
|
if error_struct.is_a?(Hash) && error_struct[path.last].is_a?(String)
|
|
76
|
-
RestErrorAnalyzer.add_error(
|
|
78
|
+
RestErrorAnalyzer.add_error(context, type, error_struct[path.last])
|
|
77
79
|
error_struct.each do |k, v|
|
|
78
80
|
next if k.eql?(path.last)
|
|
79
|
-
RestErrorAnalyzer.add_error(
|
|
81
|
+
RestErrorAnalyzer.add_error(context, "#{type}(sub)", "#{k}: #{v}") if [String, Integer].include?(v.class)
|
|
80
82
|
end
|
|
81
83
|
end
|
|
82
84
|
end
|
|
@@ -84,20 +86,20 @@ module Aspera
|
|
|
84
86
|
end
|
|
85
87
|
|
|
86
88
|
class << self
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
# @param
|
|
90
|
-
# @param type
|
|
91
|
-
# @param
|
|
92
|
-
def add_error(
|
|
93
|
-
|
|
94
|
-
Log.log.trace1{"Found error: #{type}: #{
|
|
89
|
+
# Used by handler to add an error description to list of errors
|
|
90
|
+
# For logging and tracing : collect error descriptions (create file to activate)
|
|
91
|
+
# @param context [Hash] the result context, provided to handler
|
|
92
|
+
# @param type [String] type of exception, for logging purpose
|
|
93
|
+
# @param message [String] one error message to add to list
|
|
94
|
+
def add_error(context, type, message)
|
|
95
|
+
context[:messages].push(message)
|
|
96
|
+
Log.log.trace1{"Found error: #{type}: #{message}"}
|
|
95
97
|
log_file = instance.log_file
|
|
96
98
|
# log error for further analysis (file must exist to activate)
|
|
97
99
|
return if log_file.nil? || !File.exist?(log_file)
|
|
98
100
|
File.open(log_file, 'a+') do |f|
|
|
99
|
-
f.write("\n=#{type}=====\n#{
|
|
100
|
-
"#{JSON.generate(
|
|
101
|
+
f.write("\n=#{type}=====\n#{context[:request].method} #{context[:request].path}\n#{context[:response].code}\n" \
|
|
102
|
+
"#{JSON.generate(context[:data])}\n#{context[:messages].join("\n")}")
|
|
101
103
|
end
|
|
102
104
|
end
|
|
103
105
|
end
|
|
@@ -17,48 +17,49 @@ module Aspera
|
|
|
17
17
|
RestErrorAnalyzer.instance.add_simple_handler(name: 'Type 3: error:internal_message', path: %w[error internal_message])
|
|
18
18
|
RestErrorAnalyzer.instance.add_simple_handler(name: 'Type 5', path: ['error_description'])
|
|
19
19
|
RestErrorAnalyzer.instance.add_simple_handler(name: 'Type 6', path: ['message'])
|
|
20
|
+
RestErrorAnalyzer.instance.add_simple_handler(name: 'Type 6', path: ['failure'], always: true)
|
|
20
21
|
# AoC Automation
|
|
21
22
|
RestErrorAnalyzer.instance.add_simple_handler(name: 'AoC Automation', path: ['error'])
|
|
22
|
-
RestErrorAnalyzer.instance.add_handler('Type 7: errors[]') do |type,
|
|
23
|
-
next unless
|
|
23
|
+
RestErrorAnalyzer.instance.add_handler('Type 7: errors[]') do |type, context|
|
|
24
|
+
next unless context[:data].is_a?(Hash) && context[:data]['errors'].is_a?(Hash)
|
|
24
25
|
# special for Shares: false positive ? (update global transfer_settings)
|
|
25
|
-
next if
|
|
26
|
-
|
|
27
|
-
RestErrorAnalyzer.add_error(
|
|
26
|
+
next if context[:data].key?('min_connect_version')
|
|
27
|
+
context[:data]['errors'].each do |k, v|
|
|
28
|
+
RestErrorAnalyzer.add_error(context, type, "#{k}: #{v}")
|
|
28
29
|
end
|
|
29
30
|
end
|
|
30
31
|
# call to upload_setup and download_setup of node api
|
|
31
|
-
RestErrorAnalyzer.instance.add_handler('T8:node: *_setup') do |type,
|
|
32
|
-
next unless
|
|
33
|
-
d_t_s =
|
|
32
|
+
RestErrorAnalyzer.instance.add_handler('T8:node: *_setup') do |type, context|
|
|
33
|
+
next unless context[:data].is_a?(Hash)
|
|
34
|
+
d_t_s = context[:data]['transfer_specs']
|
|
34
35
|
next unless d_t_s.is_a?(Array)
|
|
35
36
|
d_t_s.each do |res|
|
|
36
37
|
r_err = res.dig(*%w[transfer_spec error]) || res['error']
|
|
37
38
|
next unless r_err.is_a?(Hash)
|
|
38
|
-
RestErrorAnalyzer.add_error(
|
|
39
|
+
RestErrorAnalyzer.add_error(context, type, r_err.values.join(': '))
|
|
39
40
|
end
|
|
40
41
|
end
|
|
41
42
|
RestErrorAnalyzer.instance.add_simple_handler(name: 'T9:IBM cloud IAM', path: ['errorMessage'])
|
|
42
43
|
RestErrorAnalyzer.instance.add_simple_handler(name: 'T10:faspex v4', path: ['user_message'])
|
|
43
|
-
RestErrorAnalyzer.instance.add_handler('bss graphql') do |type,
|
|
44
|
-
next unless
|
|
45
|
-
d_t_s =
|
|
44
|
+
RestErrorAnalyzer.instance.add_handler('bss graphql') do |type, context|
|
|
45
|
+
next unless context[:data].is_a?(Hash)
|
|
46
|
+
d_t_s = context[:data]['errors']
|
|
46
47
|
next unless d_t_s.is_a?(Array)
|
|
47
48
|
d_t_s.each do |res|
|
|
48
49
|
r_err = res['message']
|
|
49
50
|
next unless r_err.is_a?(String)
|
|
50
|
-
RestErrorAnalyzer.add_error(
|
|
51
|
+
RestErrorAnalyzer.add_error(context, type, r_err)
|
|
51
52
|
end
|
|
52
53
|
end
|
|
53
|
-
RestErrorAnalyzer.instance.add_handler('Orchestrator') do |type,
|
|
54
|
-
next if
|
|
55
|
-
data =
|
|
54
|
+
RestErrorAnalyzer.instance.add_handler('Orchestrator') do |type, context|
|
|
55
|
+
next if context[:response].code.start_with?('2')
|
|
56
|
+
data = context[:data]
|
|
56
57
|
next unless data.is_a?(Hash)
|
|
57
58
|
work_order = data['work_order']
|
|
58
59
|
next unless work_order.is_a?(Hash)
|
|
59
|
-
RestErrorAnalyzer.add_error(
|
|
60
|
+
RestErrorAnalyzer.add_error(context, type, work_order['statusDetails'])
|
|
60
61
|
data['missing_parameters']&.each do |param|
|
|
61
|
-
RestErrorAnalyzer.add_error(
|
|
62
|
+
RestErrorAnalyzer.add_error(context, type, "missing parameter: #{param}")
|
|
62
63
|
end
|
|
63
64
|
end
|
|
64
65
|
end
|
data/lib/aspera/transfer/spec.rb
CHANGED
|
@@ -25,6 +25,7 @@ module Aspera
|
|
|
25
25
|
TRANSPORT_FIELDS = (%w[remote_host] + AK_TSPEC_BASE.keys + WSS_FIELDS).freeze
|
|
26
26
|
# reserved tag for Aspera
|
|
27
27
|
TAG_RESERVED = 'aspera'
|
|
28
|
+
SPECIFIC = %w{token paths direction source_root destination_root}.freeze
|
|
28
29
|
class << self
|
|
29
30
|
# wrong def in transferd
|
|
30
31
|
POLICY_FIX = {
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: aspera-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.25.
|
|
4
|
+
version: 4.25.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Laurent Martin
|
|
@@ -454,7 +454,7 @@ metadata:
|
|
|
454
454
|
allowed_push_host: https://rubygems.org
|
|
455
455
|
homepage_uri: https://github.com/IBM/aspera-cli
|
|
456
456
|
source_code_uri: https://github.com/IBM/aspera-cli/tree/main/lib/aspera
|
|
457
|
-
changelog_uri: https://github.com/IBM/aspera-cli/CHANGELOG.md
|
|
457
|
+
changelog_uri: https://github.com/IBM/aspera-cli/blob/main/CHANGELOG.md
|
|
458
458
|
rubygems_uri: https://rubygems.org/gems/aspera-cli
|
|
459
459
|
documentation_uri: https://www.rubydoc.info/gems/aspera-cli
|
|
460
460
|
rdoc_options: []
|
metadata.gz.sig
CHANGED
|
Binary file
|