aspera-cli 4.24.2 → 4.25.0.pre2
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 +1067 -758
- data/CONTRIBUTING.md +93 -120
- data/README.md +817 -510
- data/lib/aspera/agent/direct.rb +14 -12
- data/lib/aspera/agent/transferd.rb +4 -4
- data/lib/aspera/api/aoc.rb +71 -43
- data/lib/aspera/api/cos_node.rb +3 -2
- data/lib/aspera/api/faspex.rb +6 -5
- data/lib/aspera/api/node.rb +10 -12
- data/lib/aspera/ascmd.rb +1 -2
- data/lib/aspera/ascp/installation.rb +55 -41
- data/lib/aspera/ascp/management.rb +9 -5
- data/lib/aspera/assert.rb +28 -6
- data/lib/aspera/cli/error.rb +4 -2
- data/lib/aspera/cli/extended_value.rb +94 -62
- data/lib/aspera/cli/formatter.rb +55 -22
- data/lib/aspera/cli/main.rb +21 -14
- data/lib/aspera/cli/manager.rb +349 -248
- data/lib/aspera/cli/plugins/alee.rb +3 -3
- data/lib/aspera/cli/plugins/aoc.rb +94 -51
- data/lib/aspera/cli/plugins/base.rb +62 -49
- data/lib/aspera/cli/plugins/config.rb +85 -96
- data/lib/aspera/cli/plugins/console.rb +15 -9
- data/lib/aspera/cli/plugins/cos.rb +1 -1
- data/lib/aspera/cli/plugins/faspex.rb +34 -27
- data/lib/aspera/cli/plugins/faspex5.rb +47 -44
- data/lib/aspera/cli/plugins/faspio.rb +7 -6
- data/lib/aspera/cli/plugins/httpgw.rb +3 -2
- data/lib/aspera/cli/plugins/node.rb +132 -120
- data/lib/aspera/cli/plugins/oauth.rb +1 -1
- data/lib/aspera/cli/plugins/orchestrator.rb +116 -33
- data/lib/aspera/cli/plugins/preview.rb +26 -46
- data/lib/aspera/cli/plugins/server.rb +9 -10
- data/lib/aspera/cli/plugins/shares.rb +77 -43
- data/lib/aspera/cli/sync_actions.rb +49 -38
- data/lib/aspera/cli/transfer_agent.rb +16 -34
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +8 -5
- data/lib/aspera/command_line_builder.rb +20 -17
- data/lib/aspera/coverage.rb +6 -2
- data/lib/aspera/environment.rb +71 -84
- data/lib/aspera/faspex_gw.rb +1 -1
- data/lib/aspera/faspex_postproc.rb +1 -1
- data/lib/aspera/keychain/factory.rb +1 -2
- data/lib/aspera/keychain/macos_security.rb +2 -2
- data/lib/aspera/log.rb +2 -1
- data/lib/aspera/markdown.rb +31 -0
- data/lib/aspera/nagios.rb +6 -5
- data/lib/aspera/oauth/base.rb +17 -27
- data/lib/aspera/oauth/factory.rb +1 -1
- data/lib/aspera/oauth/url_json.rb +2 -1
- data/lib/aspera/preview/file_types.rb +23 -37
- data/lib/aspera/preview/terminal.rb +95 -29
- data/lib/aspera/preview/utils.rb +6 -5
- data/lib/aspera/products/connect.rb +3 -3
- data/lib/aspera/rest.rb +51 -39
- data/lib/aspera/rest_error_analyzer.rb +4 -4
- data/lib/aspera/ssh.rb +5 -2
- data/lib/aspera/ssl.rb +41 -0
- data/lib/aspera/sync/conf.schema.yaml +182 -34
- data/lib/aspera/sync/database.rb +2 -1
- data/lib/aspera/sync/operations.rb +128 -72
- data/lib/aspera/transfer/parameters.rb +3 -4
- data/lib/aspera/transfer/spec.rb +2 -3
- data/lib/aspera/transfer/spec.schema.yaml +49 -19
- data/lib/aspera/transfer/spec_doc.rb +14 -14
- data/lib/aspera/uri_reader.rb +1 -1
- data/lib/transferd_pb.rb +2 -2
- data.tar.gz.sig +0 -0
- metadata +33 -6
- metadata.gz.sig +0 -0
|
@@ -21,6 +21,30 @@ module Aspera
|
|
|
21
21
|
class Node < BasicAuth
|
|
22
22
|
include SyncActions
|
|
23
23
|
|
|
24
|
+
# Processing of paths in arguments and results
|
|
25
|
+
# Used only by Faspex4 to browse packages
|
|
26
|
+
class NodePathPrefix
|
|
27
|
+
def initialize(path)
|
|
28
|
+
@root = path
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# get next path argument from command line, and add prefix
|
|
32
|
+
def add_to_path(path_arg)
|
|
33
|
+
File.join(@root, path_arg)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# get remaining path arguments from command line, and add prefix
|
|
37
|
+
def add_to_paths!(path_args)
|
|
38
|
+
path_args.map!{ |p| add_to_path(p)}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def remove_in_object_list!(obj_list)
|
|
42
|
+
obj_list.each do |item|
|
|
43
|
+
item['path'] = item['path'][@root.length..-1] if item['path'].start_with?(@root)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
24
48
|
class << self
|
|
25
49
|
# directory: node, container: shares
|
|
26
50
|
FOLDER_TYPES = %w[directory container].freeze
|
|
@@ -30,6 +54,7 @@ module Aspera
|
|
|
30
54
|
'HSTS Node API'
|
|
31
55
|
end
|
|
32
56
|
|
|
57
|
+
# @return [Hash,NilClass]
|
|
33
58
|
def detect(address_or_url)
|
|
34
59
|
urls = if address_or_url.match?(%r{^[a-z]{1,6}://})
|
|
35
60
|
[address_or_url]
|
|
@@ -45,12 +70,12 @@ module Aspera
|
|
|
45
70
|
next unless base_url.match?('https?://')
|
|
46
71
|
api = Rest.new(base_url: base_url)
|
|
47
72
|
test_endpoint = 'ping'
|
|
48
|
-
|
|
49
|
-
next unless
|
|
73
|
+
http = api.read(test_endpoint, ret: :resp)
|
|
74
|
+
next unless http.body.eql?('')
|
|
50
75
|
# also remove "/"
|
|
51
76
|
url_end = -2 - test_endpoint.length
|
|
52
77
|
return {
|
|
53
|
-
url:
|
|
78
|
+
url: http.uri.to_s[0..url_end],
|
|
54
79
|
version: 'requires authentication'
|
|
55
80
|
}
|
|
56
81
|
rescue StandardError => e
|
|
@@ -68,11 +93,11 @@ module Aspera
|
|
|
68
93
|
options.declare(:validator, 'Identifier of validator (optional for central)')
|
|
69
94
|
options.declare(:asperabrowserurl, 'URL for simple aspera web ui', default: 'https://asperabrowser.mybluemix.net')
|
|
70
95
|
options.declare(
|
|
71
|
-
:default_ports, 'Gen4: Use standard FASP ports (true) or get from node API (false)',
|
|
96
|
+
:default_ports, 'Gen4: Use standard FASP ports (true) or get from node API (false)', allowed: Allowed::TYPES_BOOLEAN, default: true,
|
|
72
97
|
handler: {o: Api::Node, m: :use_standard_ports}
|
|
73
98
|
)
|
|
74
99
|
options.declare(
|
|
75
|
-
:node_cache, 'Gen4: Set to no to force actual file system read',
|
|
100
|
+
:node_cache, 'Gen4: Set to no to force actual file system read', allowed: Allowed::TYPES_BOOLEAN,
|
|
76
101
|
handler: {o: Api::Node, m: :use_node_cache}
|
|
77
102
|
)
|
|
78
103
|
options.declare(:root_id, 'Gen4: File id of top folder when using access key (override AK root id)')
|
|
@@ -114,7 +139,7 @@ module Aspera
|
|
|
114
139
|
SEARCH_REMOVE_FIELDS = %w[basename permissions].freeze
|
|
115
140
|
|
|
116
141
|
# Actions in execute_command_gen3
|
|
117
|
-
COMMANDS_GEN3 = %i[search space mkdir mklink mkfile rename delete browse upload download cat sync transport]
|
|
142
|
+
COMMANDS_GEN3 = %i[search space mkdir mklink mkfile rename delete browse upload download cat sync transport spec]
|
|
118
143
|
|
|
119
144
|
BASE_ACTIONS = %i[api_details].concat(COMMANDS_GEN3).freeze
|
|
120
145
|
|
|
@@ -142,9 +167,9 @@ module Aspera
|
|
|
142
167
|
GEN4_LS_FIELDS = %w[name type recursive_size size modified_time access_level].freeze
|
|
143
168
|
|
|
144
169
|
# @param api [Rest] an existing API object for the Node API
|
|
145
|
-
# @param prefix_path [String,nil] for Faspex 4, allows browsing a package
|
|
170
|
+
# @param prefix_path [String,nil] for Faspex 4, allows browsing a package without full path in node (removes storage prefix)
|
|
146
171
|
def initialize(context:, api: nil, prefix_path: nil)
|
|
147
|
-
@
|
|
172
|
+
@prefixer = prefix_path ? NodePathPrefix.new(prefix_path) : nil
|
|
148
173
|
super(context: context, basic_options: api.nil?)
|
|
149
174
|
Node.declare_options(options)
|
|
150
175
|
return if context.only_manual?
|
|
@@ -171,43 +196,12 @@ module Aspera
|
|
|
171
196
|
end
|
|
172
197
|
end
|
|
173
198
|
|
|
174
|
-
# reduce the path from a result on given named column
|
|
175
|
-
def c_result_remove_prefix_path(result, column)
|
|
176
|
-
return result if @prefix_path.nil?
|
|
177
|
-
case result[:type]
|
|
178
|
-
when :object_list
|
|
179
|
-
result[:data].each do |item|
|
|
180
|
-
item[column] = item[column][@prefix_path.length..-1] if item[column].start_with?(@prefix_path)
|
|
181
|
-
end
|
|
182
|
-
when :single_object
|
|
183
|
-
item = result[:data]
|
|
184
|
-
item[column] = item[column][@prefix_path.length..-1] if item[column].start_with?(@prefix_path)
|
|
185
|
-
end
|
|
186
|
-
return result
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
# translates paths results into CLI result, and removes prefix
|
|
190
|
-
def c_result_translate_rem_prefix(response, type, success_msg)
|
|
191
|
-
errors = []
|
|
192
|
-
final_result = {type: :object_list, data: [], fields: [type, 'result']}
|
|
193
|
-
response['paths'].each do |p|
|
|
194
|
-
result = success_msg
|
|
195
|
-
if p.key?('error')
|
|
196
|
-
Log.log.error{"#{p['error']['user_message']} : #{p['path']}"}
|
|
197
|
-
result = p['error']['user_message']
|
|
198
|
-
errors.push([p['path'], p['error']['user_message']])
|
|
199
|
-
end
|
|
200
|
-
final_result[:data].push({type => p['path'], 'result' => result})
|
|
201
|
-
end
|
|
202
|
-
# one error make all fail
|
|
203
|
-
raise errors.map{ |i| "#{i.first}: #{i.last}"}.join(', ') unless errors.empty?
|
|
204
|
-
return c_result_remove_prefix_path(final_result, type)
|
|
205
|
-
end
|
|
206
|
-
|
|
207
199
|
# Gen3 API
|
|
208
200
|
def browse_gen3
|
|
209
|
-
folders_to_process =
|
|
210
|
-
|
|
201
|
+
folders_to_process = options.get_next_argument('path', validation: String)
|
|
202
|
+
folders_to_process = @prefixer.add_to_path(folders_to_process) unless @prefixer.nil?
|
|
203
|
+
folders_to_process = [folders_to_process]
|
|
204
|
+
query = options.get_option(:query) || {}
|
|
211
205
|
# special parameter: max number of entries in result
|
|
212
206
|
max_items = query.delete(MAX_ITEMS)
|
|
213
207
|
# special parameter: recursive browsing
|
|
@@ -225,14 +219,13 @@ module Aspera
|
|
|
225
219
|
query['path'] = path
|
|
226
220
|
offset = 0
|
|
227
221
|
total_count = nil
|
|
228
|
-
result = nil
|
|
229
222
|
loop do
|
|
230
223
|
# example: send_result={'items'=>[{'file'=>"filename1","permissions"=>[{'name'=>'read'},{'name'=>'write'}]}]}
|
|
231
224
|
response = @api_node.create('files/browse', query)
|
|
232
225
|
# 'file','symbolic_link'
|
|
233
226
|
if !Node.gen3_entry_folder?(response['self']) || only_path
|
|
234
|
-
|
|
235
|
-
|
|
227
|
+
@prefixer&.remove_in_object_list!([response['self']])
|
|
228
|
+
return Main.result_single_object(response['self'])
|
|
236
229
|
end
|
|
237
230
|
items = response['items']
|
|
238
231
|
total_count ||= response['total_count']
|
|
@@ -253,9 +246,10 @@ module Aspera
|
|
|
253
246
|
end
|
|
254
247
|
query.delete('skip')
|
|
255
248
|
end
|
|
256
|
-
|
|
249
|
+
@prefixer&.remove_in_object_list!(all_items)
|
|
250
|
+
return Main.result_object_list(all_items)
|
|
251
|
+
ensure
|
|
257
252
|
formatter.long_operation_terminated
|
|
258
|
-
return c_result_remove_prefix_path(result, 'path')
|
|
259
253
|
end
|
|
260
254
|
|
|
261
255
|
# Create async transfer spec request from direction and folders
|
|
@@ -294,48 +288,57 @@ module Aspera
|
|
|
294
288
|
case command
|
|
295
289
|
when :delete
|
|
296
290
|
# TODO: add query for recursive
|
|
297
|
-
paths_to_delete =
|
|
291
|
+
paths_to_delete = options.get_next_argument('file list', multiple: true)
|
|
292
|
+
@prefixer&.add_to_paths!(paths_to_delete)
|
|
298
293
|
resp = @api_node.create('files/delete', {paths: paths_to_delete.map{ |i| {'path' => i.start_with?('/') ? i : "/#{i}"}}})
|
|
299
|
-
return
|
|
294
|
+
return cli_result_from_paths_response(resp, 'file deleted')
|
|
300
295
|
when :search
|
|
301
|
-
search_root =
|
|
296
|
+
search_root = options.get_next_argument('search root', validation: String)
|
|
297
|
+
search_root = @prefixer.add_to_path(search_root) unless @prefixer.nil?
|
|
302
298
|
parameters = {'path' => search_root}
|
|
303
299
|
other_options = options.get_option(:query)
|
|
304
300
|
parameters.merge!(other_options) unless other_options.nil?
|
|
305
301
|
resp = @api_node.create('files/search', parameters)
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
result[:fields] = result[:data].first.keys.reject{ |i| SEARCH_REMOVE_FIELDS.include?(i)}
|
|
302
|
+
return Main.result_empty if resp['items'].empty?
|
|
303
|
+
fields = resp['items'].first.keys.reject{ |i| SEARCH_REMOVE_FIELDS.include?(i)}
|
|
309
304
|
formatter.display_item_count(resp['item_count'], resp['total_count'])
|
|
310
305
|
formatter.display_status("params: #{resp['parameters'].keys.map{ |k| "#{k}:#{resp['parameters'][k]}"}.join(',')}")
|
|
311
|
-
|
|
306
|
+
@prefixer&.remove_in_object_list!(resp['items'])
|
|
307
|
+
return Main.result_object_list(resp['items'], fields: fields)
|
|
312
308
|
when :space
|
|
313
|
-
path_list =
|
|
309
|
+
path_list = options.get_next_argument('folder path or ext.val. list', multiple: true)
|
|
310
|
+
@prefixer&.add_to_paths!(path_list)
|
|
314
311
|
resp = @api_node.create('space', {'paths' => path_list.map{ |i| {path: i}}})
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
return c_result_remove_prefix_path(result, 'path')
|
|
312
|
+
@prefixer&.remove_in_object_list!(resp['paths'])
|
|
313
|
+
return Main.result_object_list(resp['paths'])
|
|
318
314
|
when :mkdir
|
|
319
|
-
path_list =
|
|
315
|
+
path_list = options.get_next_argument('folder path or ext.val. list', multiple: true)
|
|
316
|
+
@prefixer&.add_to_paths!(path_list)
|
|
320
317
|
resp = @api_node.create('files/create', {'paths' => path_list.map{ |i| {type: :directory, path: i}}})
|
|
321
|
-
return
|
|
318
|
+
return cli_result_from_paths_response(resp, 'folder created')
|
|
322
319
|
when :mklink
|
|
323
|
-
target =
|
|
324
|
-
|
|
320
|
+
target = options.get_next_argument('target', validation: String)
|
|
321
|
+
target = @prefixer.add_to_path(target) unless @prefixer.nil?
|
|
322
|
+
one_path = options.get_next_argument('link path', validation: String)
|
|
323
|
+
one_path = @prefixer.add_to_path(one_path) unless @prefixer.nil?
|
|
325
324
|
resp = @api_node.create('files/create', {'paths' => [{type: :symbolic_link, path: one_path, target: {path: target}}]})
|
|
326
|
-
return
|
|
325
|
+
return cli_result_from_paths_response(resp, 'link created')
|
|
327
326
|
when :mkfile
|
|
328
|
-
one_path =
|
|
327
|
+
one_path = options.get_next_argument('file path', validation: String)
|
|
328
|
+
one_path = @prefixer.add_to_path(one_path) unless @prefixer.nil?
|
|
329
329
|
contents64 = Base64.strict_encode64(options.get_next_argument('contents'))
|
|
330
330
|
resp = @api_node.create('files/create', {'paths' => [{type: :file, path: one_path, contents: contents64}]})
|
|
331
|
-
return
|
|
331
|
+
return cli_result_from_paths_response(resp, 'file created')
|
|
332
332
|
when :rename
|
|
333
333
|
# TODO: multiple ?
|
|
334
|
-
path_base =
|
|
335
|
-
|
|
336
|
-
|
|
334
|
+
path_base = options.get_next_argument('path_base', validation: String)
|
|
335
|
+
path_base = @prefixer.add_to_path(path_base) unless @prefixer.nil?
|
|
336
|
+
path_src = options.get_next_argument('path_src', validation: String)
|
|
337
|
+
path_src = @prefixer.add_to_path(path_src) unless @prefixer.nil?
|
|
338
|
+
path_dst = options.get_next_argument('path_dst', validation: String)
|
|
339
|
+
path_dst = @prefixer.add_to_path(path_dst) unless @prefixer.nil?
|
|
337
340
|
resp = @api_node.create('files/rename', {'paths' => [{'path' => path_base, 'source' => path_src, 'destination' => path_dst}]})
|
|
338
|
-
return
|
|
341
|
+
return cli_result_from_paths_response(resp, 'entry moved')
|
|
339
342
|
when :browse
|
|
340
343
|
return browse_gen3
|
|
341
344
|
when :sync
|
|
@@ -377,15 +380,15 @@ module Aspera
|
|
|
377
380
|
transfer_spec.delete('paths') if command.eql?(:upload)
|
|
378
381
|
return Main.result_transfer(transfer.start(transfer_spec))
|
|
379
382
|
when :cat
|
|
380
|
-
remote_path =
|
|
383
|
+
remote_path = options.get_next_argument('remote path', validation: String)
|
|
384
|
+
remote_path = @prefixer.add_to_path(remote_path) unless @prefixer.nil?
|
|
381
385
|
File.basename(remote_path)
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
subpath: "files/#{URI.encode_www_form_component(remote_path)}/contents"
|
|
385
|
-
)
|
|
386
|
-
return Main.result_text(result[:http].body)
|
|
386
|
+
http = @api_node.read("files/#{URI.encode_www_form_component(remote_path)}/contents", ret: :resp)
|
|
387
|
+
return Main.result_text(http.body)
|
|
387
388
|
when :transport
|
|
388
389
|
return Main.result_single_object(@api_node.transport_params)
|
|
390
|
+
when :spec
|
|
391
|
+
return Main.result_single_object(@api_node.base_spec)
|
|
389
392
|
end
|
|
390
393
|
Aspera.error_unreachable_line
|
|
391
394
|
end
|
|
@@ -438,7 +441,7 @@ module Aspera
|
|
|
438
441
|
nagios.add_ok('node api', 'accessible')
|
|
439
442
|
nagios.check_time_offset(info['current_time'], 'node api')
|
|
440
443
|
nagios.check_product_version('node api', 'entsrv', info['version'])
|
|
441
|
-
rescue
|
|
444
|
+
rescue StandardError => e
|
|
442
445
|
nagios.add_critical('node api', e.to_s)
|
|
443
446
|
end
|
|
444
447
|
begin
|
|
@@ -447,13 +450,14 @@ module Aspera
|
|
|
447
450
|
subpath: 'services/soap/Transfer-201210',
|
|
448
451
|
content_type: Rest::MIME_TEXT,
|
|
449
452
|
body: CENTRAL_SOAP_API_TEST,
|
|
450
|
-
headers: {'Content-Type' => 'text/xml;charset=UTF-8', 'SOAPAction' => 'FASPSessionNET-200911#GetSessionInfo'}
|
|
451
|
-
|
|
453
|
+
headers: {'Content-Type' => 'text/xml;charset=UTF-8', 'SOAPAction' => 'FASPSessionNET-200911#GetSessionInfo'},
|
|
454
|
+
ret: :resp
|
|
455
|
+
).body
|
|
452
456
|
nagios.add_ok('central', 'accessible by node')
|
|
453
457
|
rescue StandardError => e
|
|
454
458
|
nagios.add_critical('central', e.to_s)
|
|
455
459
|
end
|
|
456
|
-
|
|
460
|
+
Main.result_object_list(nagios.status_list)
|
|
457
461
|
when :events
|
|
458
462
|
events = @api_node.read('events', query_read_delete)
|
|
459
463
|
return Main.result_object_list(events, fields: ->(f){!f.start_with?('data')})
|
|
@@ -513,8 +517,8 @@ module Aspera
|
|
|
513
517
|
else Aspera.error_unreachable_line
|
|
514
518
|
end
|
|
515
519
|
return Main.result_single_object(result) if command_repo.eql?(:node_info)
|
|
516
|
-
|
|
517
|
-
OAuth::Factory.
|
|
520
|
+
raise BadArgument, 'Cannot get bearer token if authenticating with secret' unless apifid[:api].auth_params[:type].eql?(:oauth2)
|
|
521
|
+
Aspera.assert(OAuth::Factory.bearer_auth?(result[:password])){'Not using bearer token auth'}
|
|
518
522
|
return Main.result_text(result[:password])
|
|
519
523
|
when :browse
|
|
520
524
|
apifid = apifid_from_next_arg(top_file_id)
|
|
@@ -531,7 +535,7 @@ module Aspera
|
|
|
531
535
|
when :mkdir, :mklink, :mkfile
|
|
532
536
|
containing_folder_path, new_item = Api::Node.split_folder(options.get_next_argument('path'))
|
|
533
537
|
apifid = @api_node.resolve_api_fid(top_file_id, containing_folder_path, true)
|
|
534
|
-
query = options.get_option(:query
|
|
538
|
+
query = options.get_option(:query)
|
|
535
539
|
check_exists = true
|
|
536
540
|
payload = {name: new_item}
|
|
537
541
|
if query
|
|
@@ -570,10 +574,11 @@ module Aspera
|
|
|
570
574
|
return Main.result_status("renamed to #{newname}")
|
|
571
575
|
when :delete
|
|
572
576
|
return do_bulk_operation(command: command_repo, descr: 'path', values: String, id_result: 'path') do |l_path|
|
|
573
|
-
apifid = if (m =
|
|
577
|
+
apifid = if (m = Base.percent_selector(l_path))
|
|
578
|
+
Aspera.assert_values(m[:field], ['id'], type: BadIdentifier)
|
|
574
579
|
{
|
|
575
580
|
api: @api_node,
|
|
576
|
-
file_id: m[
|
|
581
|
+
file_id: m[:value]
|
|
577
582
|
}
|
|
578
583
|
else
|
|
579
584
|
@api_node.resolve_api_fid(top_file_id, l_path)
|
|
@@ -602,11 +607,8 @@ module Aspera
|
|
|
602
607
|
return Main.result_transfer(transfer.start(apifid[:api].transfer_spec_gen4(apifid[:file_id], Transfer::Spec::DIRECTION_RECEIVE, {'paths'=>source_paths})))
|
|
603
608
|
when :cat
|
|
604
609
|
apifid = apifid_from_next_arg(top_file_id)
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
subpath: "files/#{apifid[:file_id]}/content"
|
|
608
|
-
)
|
|
609
|
-
return Main.result_text(result[:http].body)
|
|
610
|
+
http = apifid[:api].read("files/#{apifid[:file_id]}/content", ret: :resp)
|
|
611
|
+
return Main.result_text(http.body)
|
|
610
612
|
when :show
|
|
611
613
|
apifid = apifid_from_next_arg(top_file_id)
|
|
612
614
|
items = apifid[:api].read("files/#{apifid[:file_id]}")
|
|
@@ -618,12 +620,8 @@ module Aspera
|
|
|
618
620
|
return Main.result_status('Done')
|
|
619
621
|
when :thumbnail
|
|
620
622
|
apifid = apifid_from_next_arg(top_file_id)
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
subpath: "files/#{apifid[:file_id]}/preview",
|
|
624
|
-
headers: {'Accept' => 'image/png'}
|
|
625
|
-
)
|
|
626
|
-
return Main.result_image(result[:http].body)
|
|
623
|
+
http = apifid[:api].read("files/#{apifid[:file_id]}/preview", headers: {'Accept' => 'image/png'}, ret: :resp)
|
|
624
|
+
return Main.result_image(http.body)
|
|
627
625
|
when :permission
|
|
628
626
|
apifid = apifid_from_next_arg(top_file_id)
|
|
629
627
|
command_perm = options.get_next_command(%i[list show create delete])
|
|
@@ -677,7 +675,7 @@ module Aspera
|
|
|
677
675
|
async_ids = @api_node.read('async/list')['sync_ids']
|
|
678
676
|
summaries = @api_node.create('async/summary', {'syncs' => async_ids})['sync_summaries']
|
|
679
677
|
selected = summaries.find{ |s| s['name'].eql?(value)}
|
|
680
|
-
raise Cli::BadIdentifier.new('sync',
|
|
678
|
+
raise Cli::BadIdentifier.new('sync', value, field: field) if selected.nil?
|
|
681
679
|
return selected['snid']
|
|
682
680
|
end
|
|
683
681
|
|
|
@@ -762,7 +760,7 @@ module Aspera
|
|
|
762
760
|
# name is unique, so we can return
|
|
763
761
|
return id if sync_info[field].eql?(value)
|
|
764
762
|
end
|
|
765
|
-
raise Cli::BadIdentifier.new('ssync',
|
|
763
|
+
raise Cli::BadIdentifier.new('ssync', value, field: field)
|
|
766
764
|
end
|
|
767
765
|
|
|
768
766
|
WATCH_FOLDER_MUL = %i[create list].freeze
|
|
@@ -789,7 +787,7 @@ module Aspera
|
|
|
789
787
|
when :show
|
|
790
788
|
return Main.result_single_object(@api_node.read(one_res_path))
|
|
791
789
|
when :modify
|
|
792
|
-
@api_node.update(one_res_path,
|
|
790
|
+
@api_node.update(one_res_path, value_create_modify(command: 'watch_folder'))
|
|
793
791
|
return Main.result_status("#{one_res_id} updated")
|
|
794
792
|
when :delete
|
|
795
793
|
@api_node.delete(one_res_path)
|
|
@@ -837,12 +835,12 @@ module Aspera
|
|
|
837
835
|
operation: 'POST',
|
|
838
836
|
subpath: "asyncs/#{asyncs_id}/#{sync_command}",
|
|
839
837
|
content_type: Rest::MIME_TEXT,
|
|
840
|
-
body: ''
|
|
841
|
-
|
|
838
|
+
body: '',
|
|
839
|
+
ret: :resp
|
|
840
|
+
).body
|
|
842
841
|
return Main.result_status('Done')
|
|
843
842
|
end
|
|
844
|
-
parameters =
|
|
845
|
-
parameters = options.get_option(:query, default: {}) if %i[bandwidth counters files].include?(sync_command)
|
|
843
|
+
parameters = options.get_option(:query) || {} if %i[bandwidth counters files].include?(sync_command)
|
|
846
844
|
return Main.result_single_object(@api_node.read("asyncs/#{asyncs_id}/#{sync_command}", parameters))
|
|
847
845
|
end
|
|
848
846
|
when :stream
|
|
@@ -895,8 +893,9 @@ module Aspera
|
|
|
895
893
|
when :sessions
|
|
896
894
|
transfers_data = @api_node.read('ops/transfers', query_read_delete)
|
|
897
895
|
sessions = transfers_data.flat_map{ |t| t['sessions']}
|
|
896
|
+
start_end = %i[start end].freeze
|
|
898
897
|
sessions.each do |session|
|
|
899
|
-
|
|
898
|
+
start_end.each do |what|
|
|
900
899
|
session["#{what}_time"] = session["#{what}_time_usec"] ? Time.at(session["#{what}_time_usec"] / 1_000_000.0).utc.iso8601(0) : nil
|
|
901
900
|
end
|
|
902
901
|
end
|
|
@@ -979,7 +978,7 @@ module Aspera
|
|
|
979
978
|
command = options.get_next_command(%i[session file])
|
|
980
979
|
validator_id = options.get_option(:validator)
|
|
981
980
|
validation = {'validator_id' => validator_id} unless validator_id.nil?
|
|
982
|
-
request_data = options.get_option(:query
|
|
981
|
+
request_data = options.get_option(:query) || {}
|
|
983
982
|
case command
|
|
984
983
|
when :session
|
|
985
984
|
command = options.get_next_command([:list])
|
|
@@ -1112,18 +1111,31 @@ module Aspera
|
|
|
1112
1111
|
|
|
1113
1112
|
private
|
|
1114
1113
|
|
|
1115
|
-
#
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1114
|
+
# Response has key `paths`.
|
|
1115
|
+
# From those, check if there is an error
|
|
1116
|
+
# @return [Array] of Hash with 2 keys: `path` and `result`
|
|
1117
|
+
def response_to_result(response, success_msg)
|
|
1118
|
+
errors = []
|
|
1119
|
+
obj_list = []
|
|
1120
|
+
response['paths'].each do |p|
|
|
1121
|
+
result = success_msg
|
|
1122
|
+
if p.key?('error')
|
|
1123
|
+
Log.log.error{"#{p['error']['user_message']} : #{p['path']}"}
|
|
1124
|
+
result = p['error']['user_message']
|
|
1125
|
+
errors.push([p['path'], p['error']['user_message']])
|
|
1126
|
+
end
|
|
1127
|
+
obj_list.push({'path' => p['path'], 'result' => result})
|
|
1128
|
+
end
|
|
1129
|
+
# one error make all fail
|
|
1130
|
+
raise errors.map{ |i| "#{i.first}: #{i.last}"}.join(', ') unless errors.empty?
|
|
1131
|
+
obj_list
|
|
1120
1132
|
end
|
|
1121
1133
|
|
|
1122
|
-
#
|
|
1123
|
-
def
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
return
|
|
1134
|
+
# Translates paths results into CLI result, and removes prefix
|
|
1135
|
+
def cli_result_from_paths_response(response, success_msg)
|
|
1136
|
+
obj_list = response_to_result(response, success_msg)
|
|
1137
|
+
@prefixer&.remove_in_object_list!(obj_list)
|
|
1138
|
+
return Main.result_object_list(obj_list, fields: %w[path result])
|
|
1127
1139
|
end
|
|
1128
1140
|
|
|
1129
1141
|
# Executes the provided API call in loop
|
|
@@ -1140,13 +1152,13 @@ module Aspera
|
|
|
1140
1152
|
item_list = []
|
|
1141
1153
|
query_token[:iteration_token] = iteration[0] unless iteration.nil?
|
|
1142
1154
|
loop do
|
|
1143
|
-
|
|
1144
|
-
Aspera.assert_type(
|
|
1155
|
+
data, http = api.call(**call_args, query: query_token, ret: :both)
|
|
1156
|
+
Aspera.assert_type(data, Array){"Expected data to be an Array, got: #{data.class}"}
|
|
1145
1157
|
# no data
|
|
1146
|
-
break if
|
|
1158
|
+
break if data.empty?
|
|
1147
1159
|
# get next iteration token from link
|
|
1148
1160
|
next_iteration_token = nil
|
|
1149
|
-
link_info =
|
|
1161
|
+
link_info = http['Link']
|
|
1150
1162
|
unless link_info.nil?
|
|
1151
1163
|
m = link_info.match(/<([^>]+)>/)
|
|
1152
1164
|
Aspera.assert(m){"Cannot parse iteration in Link: #{link_info}"}
|
|
@@ -1155,7 +1167,7 @@ module Aspera
|
|
|
1155
1167
|
# same as last iteration: stop
|
|
1156
1168
|
break if next_iteration_token&.eql?(query_token[:iteration_token])
|
|
1157
1169
|
query_token[:iteration_token] = next_iteration_token
|
|
1158
|
-
item_list.concat(
|
|
1170
|
+
item_list.concat(data)
|
|
1159
1171
|
if max&.<=(item_list.length)
|
|
1160
1172
|
item_list = item_list.slice(0, max)
|
|
1161
1173
|
break
|
|
@@ -13,7 +13,7 @@ module Aspera
|
|
|
13
13
|
AUTH_OPTIONS = %i[url auth client_id client_secret scope redirect_uri private_key passphrase username password].freeze
|
|
14
14
|
def initialize(**_)
|
|
15
15
|
super
|
|
16
|
-
options.declare(:auth, 'OAuth type of authentication',
|
|
16
|
+
options.declare(:auth, 'OAuth type of authentication', allowed: AUTH_TYPES, default: :jwt)
|
|
17
17
|
options.declare(:client_id, 'OAuth client identifier')
|
|
18
18
|
options.declare(:client_secret, 'OAuth client secret')
|
|
19
19
|
options.declare(:redirect_uri, 'OAuth (Web) redirect URI for web authentication')
|