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