aspera-cli 4.16.0 → 4.17.0
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 +50 -19
- data/CONTRIBUTING.md +3 -1
- data/README.md +965 -793
- data/bin/asession +29 -21
- data/lib/aspera/{fasp/agent_alpha.rb → agent/alpha.rb} +26 -25
- data/lib/aspera/{fasp/agent_base.rb → agent/base.rb} +15 -12
- data/lib/aspera/{fasp/agent_connect.rb → agent/connect.rb} +13 -11
- data/lib/aspera/{fasp/agent_direct.rb → agent/direct.rb} +49 -53
- data/lib/aspera/{fasp/agent_httpgw.rb → agent/httpgw.rb} +20 -19
- data/lib/aspera/{fasp/agent_node.rb → agent/node.rb} +20 -33
- data/lib/aspera/{fasp/agent_trsdk.rb → agent/trsdk.rb} +11 -11
- data/lib/aspera/api/aoc.rb +586 -0
- data/lib/aspera/api/ats.rb +46 -0
- data/lib/aspera/api/cos_node.rb +95 -0
- data/lib/aspera/api/node.rb +344 -0
- data/lib/aspera/ascmd.rb +46 -10
- data/lib/aspera/{fasp → ascp}/installation.rb +5 -5
- data/lib/aspera/{fasp → ascp}/management.rb +3 -8
- data/lib/aspera/{fasp → ascp}/products.rb +1 -1
- data/lib/aspera/assert.rb +30 -30
- data/lib/aspera/cli/basic_auth_plugin.rb +11 -10
- data/lib/aspera/cli/extended_value.rb +1 -1
- data/lib/aspera/cli/formatter.rb +13 -13
- data/lib/aspera/cli/hints.rb +5 -5
- data/lib/aspera/cli/main.rb +35 -28
- data/lib/aspera/cli/manager.rb +25 -24
- data/lib/aspera/cli/plugin.rb +22 -15
- data/lib/aspera/cli/plugin_factory.rb +61 -0
- data/lib/aspera/cli/plugins/alee.rb +7 -7
- data/lib/aspera/cli/plugins/aoc.rb +83 -77
- data/lib/aspera/cli/plugins/ats.rb +32 -33
- data/lib/aspera/cli/plugins/bss.rb +3 -4
- data/lib/aspera/cli/plugins/config.rb +169 -186
- data/lib/aspera/cli/plugins/console.rb +8 -6
- data/lib/aspera/cli/plugins/cos.rb +19 -18
- data/lib/aspera/cli/plugins/faspex.rb +61 -54
- data/lib/aspera/cli/plugins/faspex5.rb +150 -103
- data/lib/aspera/cli/plugins/node.rb +68 -73
- data/lib/aspera/cli/plugins/orchestrator.rb +34 -44
- data/lib/aspera/cli/plugins/preview.rb +31 -31
- data/lib/aspera/cli/plugins/server.rb +31 -33
- data/lib/aspera/cli/plugins/shares.rb +13 -11
- data/lib/aspera/cli/sync_actions.rb +8 -8
- data/lib/aspera/cli/transfer_agent.rb +32 -19
- data/lib/aspera/cli/transfer_progress.rb +1 -1
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +5 -0
- data/lib/aspera/command_line_builder.rb +14 -14
- data/lib/aspera/coverage.rb +1 -2
- data/lib/aspera/data_repository.rb +1 -1
- data/lib/aspera/environment.rb +2 -3
- data/lib/aspera/faspex_gw.rb +5 -6
- data/lib/aspera/faspex_postproc.rb +1 -1
- data/lib/aspera/id_generator.rb +2 -2
- data/lib/aspera/json_rpc.rb +5 -5
- data/lib/aspera/keychain/encrypted_hash.rb +6 -6
- data/lib/aspera/keychain/macos_security.rb +27 -22
- data/lib/aspera/log.rb +2 -2
- data/lib/aspera/nagios.rb +3 -3
- data/lib/aspera/node_simulator.rb +5 -6
- data/lib/aspera/oauth/base.rb +143 -0
- data/lib/aspera/oauth/factory.rb +124 -0
- data/lib/aspera/oauth/generic.rb +34 -0
- data/lib/aspera/oauth/jwt.rb +51 -0
- data/lib/aspera/oauth/url_json.rb +31 -0
- data/lib/aspera/oauth/web.rb +50 -0
- data/lib/aspera/oauth.rb +5 -331
- data/lib/aspera/open_application.rb +7 -7
- data/lib/aspera/persistency_action_once.rb +4 -4
- data/lib/aspera/persistency_folder.rb +2 -2
- data/lib/aspera/preview/generator.rb +5 -5
- data/lib/aspera/preview/terminal.rb +3 -2
- data/lib/aspera/preview/utils.rb +3 -3
- data/lib/aspera/proxy_auto_config.rb +4 -4
- data/lib/aspera/rest.rb +175 -144
- data/lib/aspera/rest_errors_aspera.rb +3 -3
- data/lib/aspera/resumer.rb +77 -0
- data/lib/aspera/ssh.rb +6 -1
- data/lib/aspera/{fasp → transfer}/error.rb +3 -3
- data/lib/aspera/{fasp → transfer}/error_info.rb +1 -1
- data/lib/aspera/{fasp → transfer}/faux_file.rb +1 -1
- data/lib/aspera/{fasp → transfer}/parameters.rb +58 -89
- data/lib/aspera/{fasp/transfer_spec.rb → transfer/spec.rb} +18 -16
- data/lib/aspera/{fasp/parameters.yaml → transfer/spec.yaml} +4 -99
- data/lib/aspera/{fasp → transfer}/sync.rb +32 -32
- data/lib/aspera/{fasp → transfer}/uri.rb +9 -8
- data/lib/aspera/web_server_simple.rb +11 -3
- data.tar.gz.sig +0 -0
- metadata +36 -63
- metadata.gz.sig +0 -0
- data/lib/aspera/aoc.rb +0 -601
- data/lib/aspera/ats_api.rb +0 -47
- data/lib/aspera/cos_node.rb +0 -94
- data/lib/aspera/fasp/resume_policy.rb +0 -79
- data/lib/aspera/node.rb +0 -339
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
# cspell:ignore snid fnid bidi ssync asyncs rund asnodeadmin mkfile mklink asperabrowser asperabrowserurl watchfolders watchfolderd entsrv
|
|
4
4
|
require 'aspera/cli/basic_auth_plugin'
|
|
5
5
|
require 'aspera/cli/sync_actions'
|
|
6
|
-
require 'aspera/
|
|
6
|
+
require 'aspera/transfer/spec'
|
|
7
7
|
require 'aspera/nagios'
|
|
8
8
|
require 'aspera/hash_ext'
|
|
9
9
|
require 'aspera/id_generator'
|
|
10
|
-
require 'aspera/node'
|
|
11
|
-
require 'aspera/aoc'
|
|
10
|
+
require 'aspera/api/node'
|
|
11
|
+
require 'aspera/api/aoc'
|
|
12
12
|
require 'aspera/oauth'
|
|
13
13
|
require 'aspera/node_simulator'
|
|
14
14
|
require 'aspera/assert'
|
|
@@ -18,10 +18,9 @@ require 'zlib'
|
|
|
18
18
|
module Aspera
|
|
19
19
|
module Cli
|
|
20
20
|
module Plugins
|
|
21
|
-
class Node <
|
|
21
|
+
class Node < Cli::BasicAuthPlugin
|
|
22
22
|
include SyncActions
|
|
23
23
|
class << self
|
|
24
|
-
@@node_options_declared = false # rubocop:disable Style/ClassVars
|
|
25
24
|
def application_name
|
|
26
25
|
'HSTS Node API'
|
|
27
26
|
end
|
|
@@ -36,7 +35,7 @@ module Aspera
|
|
|
36
35
|
"http://#{address_or_url}:9091"
|
|
37
36
|
]
|
|
38
37
|
end
|
|
39
|
-
|
|
38
|
+
error = nil
|
|
40
39
|
urls.each do |base_url|
|
|
41
40
|
next unless base_url.match?('https?://')
|
|
42
41
|
api = Rest.new(base_url: base_url)
|
|
@@ -48,8 +47,10 @@ module Aspera
|
|
|
48
47
|
url: result[:http].uri.to_s[0..url_length]
|
|
49
48
|
}
|
|
50
49
|
rescue StandardError => e
|
|
50
|
+
error = e
|
|
51
51
|
Log.log.debug{"detect error: #{e}"}
|
|
52
52
|
end
|
|
53
|
+
raise error if error
|
|
53
54
|
return nil
|
|
54
55
|
end
|
|
55
56
|
|
|
@@ -65,15 +66,13 @@ module Aspera
|
|
|
65
66
|
}
|
|
66
67
|
end
|
|
67
68
|
|
|
68
|
-
def declare_options(options
|
|
69
|
-
return if @@node_options_declared && !force
|
|
70
|
-
@@node_options_declared = true # rubocop:disable Style/ClassVars
|
|
69
|
+
def declare_options(options)
|
|
71
70
|
options.declare(:validator, 'Identifier of validator (optional for central)')
|
|
72
71
|
options.declare(:asperabrowserurl, 'URL for simple aspera web ui', default: 'https://asperabrowser.mybluemix.net')
|
|
73
72
|
options.declare(:sync_name, 'Sync name')
|
|
74
73
|
options.declare(
|
|
75
74
|
:default_ports, 'Use standard FASP ports or get from node api (gen4)', values: :bool, default: :yes,
|
|
76
|
-
handler: {o:
|
|
75
|
+
handler: {o: Api::Node, m: :use_standard_ports})
|
|
77
76
|
options.declare(:root_id, 'File id of top folder if using bearer tokens')
|
|
78
77
|
SyncActions.declare_options(options)
|
|
79
78
|
options.parse_options!
|
|
@@ -117,28 +116,29 @@ module Aspera
|
|
|
117
116
|
COMMANDS_SHARES = (BASE_ACTIONS - %i[search]).freeze
|
|
118
117
|
COMMANDS_FASPEX = COMMON_ACTIONS
|
|
119
118
|
|
|
120
|
-
def initialize(
|
|
121
|
-
super(env)
|
|
122
|
-
Node.declare_options(options
|
|
119
|
+
def initialize(api: nil, **env)
|
|
120
|
+
super(**env, basic_options: api.nil?)
|
|
121
|
+
Node.declare_options(options) if api.nil?
|
|
122
|
+
return if only_manual
|
|
123
123
|
@api_node =
|
|
124
|
-
if !api.nil?
|
|
125
|
-
# this can be
|
|
124
|
+
if !api.nil?
|
|
125
|
+
# this can be Api::Node or Rest (shares)
|
|
126
126
|
api
|
|
127
|
-
elsif
|
|
127
|
+
elsif OAuth::Factory.bearer?(options.get_option(:password, mandatory: true))
|
|
128
128
|
# info is provided like node_info of aoc
|
|
129
|
-
|
|
129
|
+
Api::Node.new(
|
|
130
130
|
base_url: options.get_option(:url, mandatory: true),
|
|
131
|
-
headers:
|
|
132
|
-
|
|
131
|
+
headers: Api::Node.bearer_headers(options.get_option(:password, mandatory: true))
|
|
132
|
+
)
|
|
133
133
|
else
|
|
134
134
|
# this is normal case
|
|
135
|
-
|
|
135
|
+
Api::Node.new(
|
|
136
136
|
base_url: options.get_option(:url, mandatory: true),
|
|
137
137
|
auth: {
|
|
138
138
|
type: :basic,
|
|
139
139
|
username: options.get_option(:username, mandatory: true),
|
|
140
140
|
password: options.get_option(:password, mandatory: true)
|
|
141
|
-
}
|
|
141
|
+
})
|
|
142
142
|
end
|
|
143
143
|
end
|
|
144
144
|
|
|
@@ -166,7 +166,7 @@ module Aspera
|
|
|
166
166
|
result = success_msg
|
|
167
167
|
if p.key?('error')
|
|
168
168
|
Log.log.error{"#{p['error']['user_message']} : #{p['path']}"}
|
|
169
|
-
result =
|
|
169
|
+
result = "ERROR: #{p['error']['user_message']}"
|
|
170
170
|
errors.push([p['path'], p['error']['user_message']])
|
|
171
171
|
end
|
|
172
172
|
final_result[:data].push({type => p['path'], 'result' => result})
|
|
@@ -192,7 +192,7 @@ module Aspera
|
|
|
192
192
|
case command
|
|
193
193
|
when :delete
|
|
194
194
|
paths_to_delete = get_next_arg_add_prefix(prefix_path, 'file list', :multiple)
|
|
195
|
-
resp = @api_node.create('files/delete', { paths: paths_to_delete.map{|i| {'path' => i.start_with?('/') ? i :
|
|
195
|
+
resp = @api_node.create('files/delete', { paths: paths_to_delete.map{|i| {'path' => i.start_with?('/') ? i : "/#{i}"} }})
|
|
196
196
|
return c_result_translate_rem_prefix(resp, 'file', 'deleted', prefix_path)
|
|
197
197
|
when :search
|
|
198
198
|
search_root = get_next_arg_add_prefix(prefix_path, 'search root')
|
|
@@ -284,7 +284,7 @@ module Aspera
|
|
|
284
284
|
request_transfer_spec[:paths] = if command.eql?(:download)
|
|
285
285
|
transfer.ts_source_paths
|
|
286
286
|
else
|
|
287
|
-
[{ destination: transfer.destination_folder(
|
|
287
|
+
[{ destination: transfer.destination_folder(Transfer::Spec::DIRECTION_SEND) }]
|
|
288
288
|
end
|
|
289
289
|
# add fixed parameters if any (for COS)
|
|
290
290
|
@api_node.add_tspec_info(request_transfer_spec) if @api_node.respond_to?(:add_tspec_info)
|
|
@@ -301,10 +301,10 @@ module Aspera
|
|
|
301
301
|
@api_node.call(
|
|
302
302
|
operation: 'GET',
|
|
303
303
|
subpath: "files/#{URI.encode_www_form_component(remote_path)}/contents",
|
|
304
|
-
save_to_file: File.join(transfer.destination_folder(
|
|
304
|
+
save_to_file: File.join(transfer.destination_folder(Transfer::Spec::DIRECTION_RECEIVE), file_name))
|
|
305
305
|
return Main.result_status("downloaded: #{file_name}")
|
|
306
306
|
end
|
|
307
|
-
error_unreachable_line
|
|
307
|
+
Aspera.error_unreachable_line
|
|
308
308
|
end
|
|
309
309
|
|
|
310
310
|
# common API to node and Shares
|
|
@@ -328,8 +328,8 @@ module Aspera
|
|
|
328
328
|
ak_info = @api_node.read("access_keys/#{access_key_id}")[:data]
|
|
329
329
|
# change API credentials if different access key
|
|
330
330
|
if !access_key_id.eql?('self')
|
|
331
|
-
@api_node.
|
|
332
|
-
@api_node.
|
|
331
|
+
@api_node.auth_params[:username] = ak_info['id']
|
|
332
|
+
@api_node.auth_params[:password] = config.lookup_secret(url: @api_node.base_url, username: ak_info['id'], mandatory: true)
|
|
333
333
|
end
|
|
334
334
|
root_file_id = ak_info['root_file_id']
|
|
335
335
|
end
|
|
@@ -381,9 +381,9 @@ module Aspera
|
|
|
381
381
|
if node_license['failure'].is_a?(String) && node_license['failure'].include?('ACL')
|
|
382
382
|
Log.log.error('server must have: asnodeadmin -mu <node user> --acl-add=internal --internal')
|
|
383
383
|
end
|
|
384
|
-
return {
|
|
384
|
+
return {type: :single_object, data: node_license}
|
|
385
385
|
when :api_details
|
|
386
|
-
return {
|
|
386
|
+
return {type: :single_object, data: {base_url: @api_node.base_url}.merge(@api_node.params)}
|
|
387
387
|
end
|
|
388
388
|
end
|
|
389
389
|
|
|
@@ -406,26 +406,26 @@ module Aspera
|
|
|
406
406
|
command_legacy = options.get_next_command(V3_IN_V4_ACTIONS)
|
|
407
407
|
# TODO: shall we support all methods here ? what if there is a link ?
|
|
408
408
|
apifid = @api_node.resolve_api_fid(top_file_id, '')
|
|
409
|
-
return Node.new(
|
|
409
|
+
return Node.new(**init_params, api: apifid[:api]).execute_action(command_legacy)
|
|
410
410
|
when :node_info, :bearer_token_node
|
|
411
411
|
apifid = @api_node.resolve_api_fid(top_file_id, options.get_next_argument('path'))
|
|
412
412
|
result = {
|
|
413
|
-
url: apifid[:api].
|
|
413
|
+
url: apifid[:api].base_url,
|
|
414
414
|
root_id: apifid[:file_id]
|
|
415
415
|
}
|
|
416
|
-
assert_values(apifid[:api].
|
|
417
|
-
case apifid[:api].
|
|
416
|
+
Aspera.assert_values(apifid[:api].auth_params[:type], %i[basic oauth2])
|
|
417
|
+
case apifid[:api].auth_params[:type]
|
|
418
418
|
when :basic
|
|
419
|
-
result[:username] = apifid[:api].
|
|
420
|
-
result[:password] = apifid[:api].
|
|
419
|
+
result[:username] = apifid[:api].auth_params[:username]
|
|
420
|
+
result[:password] = apifid[:api].auth_params[:password]
|
|
421
421
|
when :oauth2
|
|
422
|
-
result[:username] = apifid[:api].params[:headers][
|
|
422
|
+
result[:username] = apifid[:api].params[:headers][Api::Node::HEADER_X_ASPERA_ACCESS_KEY]
|
|
423
423
|
result[:password] = apifid[:api].oauth_token
|
|
424
|
-
else error_unreachable_line
|
|
424
|
+
else Aspera.error_unreachable_line
|
|
425
425
|
end
|
|
426
426
|
return {type: :single_object, data: result} if command_repo.eql?(:node_info)
|
|
427
427
|
# check format of bearer token
|
|
428
|
-
|
|
428
|
+
OAuth::Factory.bearer_extract(result[:password])
|
|
429
429
|
return Main.result_status(result[:password])
|
|
430
430
|
when :browse
|
|
431
431
|
apifid = @api_node.resolve_api_fid(top_file_id, options.get_next_argument('path'))
|
|
@@ -440,12 +440,12 @@ module Aspera
|
|
|
440
440
|
return {type: :object_list, data: items, fields: %w[name type recursive_size size modified_time access_level]}
|
|
441
441
|
when :find
|
|
442
442
|
apifid = @api_node.resolve_api_fid(top_file_id, options.get_next_argument('path'))
|
|
443
|
-
test_block =
|
|
443
|
+
test_block = Api::Node.file_matcher_from_argument(options)
|
|
444
444
|
return {type: :object_list, data: @api_node.find_files(apifid[:file_id], test_block), fields: ['path']}
|
|
445
445
|
when :mkdir
|
|
446
|
-
containing_folder_path = options.get_next_argument('path').split(
|
|
446
|
+
containing_folder_path = options.get_next_argument('path').split(Api::Node::PATH_SEPARATOR)
|
|
447
447
|
new_folder = containing_folder_path.pop
|
|
448
|
-
apifid = @api_node.resolve_api_fid(top_file_id, containing_folder_path.join(
|
|
448
|
+
apifid = @api_node.resolve_api_fid(top_file_id, containing_folder_path.join(Api::Node::PATH_SEPARATOR))
|
|
449
449
|
result = apifid[:api].create("files/#{apifid[:file_id]}/files", {name: new_folder, type: :folder})[:data]
|
|
450
450
|
return Main.result_status("created: #{result['name']} (id=#{result['id']})")
|
|
451
451
|
when :rename
|
|
@@ -464,11 +464,11 @@ module Aspera
|
|
|
464
464
|
return execute_sync_action do |sync_direction, _local_path, remote_path|
|
|
465
465
|
# Gen4 API
|
|
466
466
|
# direction is push pull, bidi
|
|
467
|
-
assert_values(sync_direction, %i[push pull bidi])
|
|
467
|
+
Aspera.assert_values(sync_direction, %i[push pull bidi])
|
|
468
468
|
ts_direction = case sync_direction
|
|
469
|
-
when :push, :bidi then
|
|
470
|
-
when :pull then
|
|
471
|
-
else error_unreachable_line
|
|
469
|
+
when :push, :bidi then Transfer::Spec::DIRECTION_SEND
|
|
470
|
+
when :pull then Transfer::Spec::DIRECTION_RECEIVE
|
|
471
|
+
else Aspera.error_unreachable_line
|
|
472
472
|
end
|
|
473
473
|
# remote is specified by option to_folder
|
|
474
474
|
apifid = @api_node.resolve_api_fid(top_file_id, remote_path)
|
|
@@ -477,8 +477,8 @@ module Aspera
|
|
|
477
477
|
transfer_spec
|
|
478
478
|
end
|
|
479
479
|
when :upload
|
|
480
|
-
apifid = @api_node.resolve_api_fid(top_file_id, transfer.destination_folder(
|
|
481
|
-
return Main.result_transfer(transfer.start(apifid[:api].transfer_spec_gen4(apifid[:file_id],
|
|
480
|
+
apifid = @api_node.resolve_api_fid(top_file_id, transfer.destination_folder(Transfer::Spec::DIRECTION_SEND))
|
|
481
|
+
return Main.result_transfer(transfer.start(apifid[:api].transfer_spec_gen4(apifid[:file_id], Transfer::Spec::DIRECTION_SEND)))
|
|
482
482
|
when :download
|
|
483
483
|
source_paths = transfer.ts_source_paths
|
|
484
484
|
# special case for AoC : all files must be in same folder
|
|
@@ -490,11 +490,11 @@ module Aspera
|
|
|
490
490
|
case file_info['type']
|
|
491
491
|
when 'file'
|
|
492
492
|
# if the single source is a file, we need to split into folder path and filename
|
|
493
|
-
src_dir_elements = source_folder.split(
|
|
493
|
+
src_dir_elements = source_folder.split(Api::Node::PATH_SEPARATOR)
|
|
494
494
|
# filename is the last one
|
|
495
495
|
source_paths = [{'source' => src_dir_elements.pop}]
|
|
496
496
|
# source folder is what remains
|
|
497
|
-
source_folder = src_dir_elements.join(
|
|
497
|
+
source_folder = src_dir_elements.join(Api::Node::PATH_SEPARATOR)
|
|
498
498
|
# TODO: instead of creating a new object, use the same, and change file id with parent folder id ? possible ?
|
|
499
499
|
apifid = @api_node.resolve_api_fid(top_file_id, source_folder)
|
|
500
500
|
when 'link', 'folder'
|
|
@@ -505,14 +505,14 @@ module Aspera
|
|
|
505
505
|
raise "Unknown source type: #{file_info['type']}"
|
|
506
506
|
end
|
|
507
507
|
end
|
|
508
|
-
return Main.result_transfer(transfer.start(apifid[:api].transfer_spec_gen4(apifid[:file_id],
|
|
508
|
+
return Main.result_transfer(transfer.start(apifid[:api].transfer_spec_gen4(apifid[:file_id], Transfer::Spec::DIRECTION_RECEIVE, {'paths'=>source_paths})))
|
|
509
509
|
when :http_node_download
|
|
510
510
|
source_paths = transfer.ts_source_paths
|
|
511
511
|
source_folder = source_paths.shift['source']
|
|
512
512
|
if source_paths.empty?
|
|
513
|
-
source_folder = source_folder.split(
|
|
513
|
+
source_folder = source_folder.split(Api::Node::PATH_SEPARATOR)
|
|
514
514
|
source_paths = [{'source' => source_folder.pop}]
|
|
515
|
-
source_folder = source_folder.join(
|
|
515
|
+
source_folder = source_folder.join(Api::Node::PATH_SEPARATOR)
|
|
516
516
|
end
|
|
517
517
|
raise Cli::BadArgument, 'one file at a time only in HTTP mode' if source_paths.length > 1
|
|
518
518
|
file_name = source_paths.first['source']
|
|
@@ -520,7 +520,7 @@ module Aspera
|
|
|
520
520
|
apifid[:api].call(
|
|
521
521
|
operation: 'GET',
|
|
522
522
|
subpath: "files/#{apifid[:file_id]}/content",
|
|
523
|
-
save_to_file: File.join(transfer.destination_folder(
|
|
523
|
+
save_to_file: File.join(transfer.destination_folder(Transfer::Spec::DIRECTION_RECEIVE), file_name))
|
|
524
524
|
return Main.result_status("downloaded: #{file_name}")
|
|
525
525
|
when :show
|
|
526
526
|
apifid = apifid_from_next_arg(top_file_id)
|
|
@@ -562,7 +562,7 @@ module Aspera
|
|
|
562
562
|
create_param = options.get_next_argument('creation data', type: Hash)
|
|
563
563
|
raise 'no file_id' if create_param.key?('file_id')
|
|
564
564
|
create_param['file_id'] = apifid[:file_id]
|
|
565
|
-
create_param['access_levels'] =
|
|
565
|
+
create_param['access_levels'] = Api::Node::ACCESS_LEVELS unless create_param.key?('access_levels')
|
|
566
566
|
# add application specific tags (AoC)
|
|
567
567
|
the_app = apifid[:api].app_info
|
|
568
568
|
the_app[:api].permissions_set_create_params(create_param: create_param, app_info: the_app) unless the_app.nil?
|
|
@@ -571,11 +571,11 @@ module Aspera
|
|
|
571
571
|
# notify application of creation
|
|
572
572
|
the_app[:api].permissions_send_event(created_data: created_data, app_info: the_app) unless the_app.nil?
|
|
573
573
|
return { type: :single_object, data: created_data}
|
|
574
|
-
else error_unreachable_line
|
|
574
|
+
else Aspera.error_unreachable_line
|
|
575
575
|
end
|
|
576
|
-
else error_unreachable_line
|
|
576
|
+
else Aspera.error_unreachable_line
|
|
577
577
|
end # command_repo
|
|
578
|
-
error_unreachable_line
|
|
578
|
+
Aspera.error_unreachable_line
|
|
579
579
|
end # execute_command_gen4
|
|
580
580
|
|
|
581
581
|
# This is older API
|
|
@@ -634,7 +634,7 @@ module Aspera
|
|
|
634
634
|
skip_ids_persistency = nil
|
|
635
635
|
if options.get_option(:once_only, mandatory: true)
|
|
636
636
|
skip_ids_persistency = PersistencyActionOnce.new(
|
|
637
|
-
manager:
|
|
637
|
+
manager: persistency,
|
|
638
638
|
data: iteration_data,
|
|
639
639
|
id: IdGenerator.from_list([
|
|
640
640
|
'sync_files',
|
|
@@ -781,7 +781,7 @@ module Aspera
|
|
|
781
781
|
# do not process last one
|
|
782
782
|
break if end_date.nil?
|
|
783
783
|
# init data for this period
|
|
784
|
-
period_bandwidth =
|
|
784
|
+
period_bandwidth = Transfer::Spec::DIRECTION_ENUM_VALUES.map(&:to_sym).each_with_object({}) do |direction, h|
|
|
785
785
|
h[direction] = dir_info.each_with_object({}) do |k2, h2|
|
|
786
786
|
h2[k2] = 0
|
|
787
787
|
end
|
|
@@ -799,7 +799,7 @@ module Aspera
|
|
|
799
799
|
info[:sessions] += 1
|
|
800
800
|
# end
|
|
801
801
|
end
|
|
802
|
-
next if
|
|
802
|
+
next if Transfer::Spec::DIRECTION_ENUM_VALUES.map(&:to_sym).all? do |dir|
|
|
803
803
|
period_bandwidth[dir][:sessions].zero?
|
|
804
804
|
end
|
|
805
805
|
result.push({start: Time.at(start_date / 1_000_000), end: Time.at(end_date / 1_000_000)}.merge(period_bandwidth))
|
|
@@ -895,7 +895,7 @@ module Aspera
|
|
|
895
895
|
}
|
|
896
896
|
# encode parameters so that it looks good in url
|
|
897
897
|
encoded_params = Base64.strict_encode64(Zlib::Deflate.deflate(JSON.generate(browse_params))).gsub(/=+$/, '').tr('+/', '-_').reverse
|
|
898
|
-
OpenApplication.instance.uri(options.get_option(:asperabrowserurl)
|
|
898
|
+
OpenApplication.instance.uri("#{options.get_option(:asperabrowserurl)}?goto=#{encoded_params}")
|
|
899
899
|
return Main.result_status('done')
|
|
900
900
|
when :basic_token
|
|
901
901
|
return Main.result_status(Rest.basic_token(options.get_option(:username, mandatory: true), options.get_option(:password, mandatory: true)))
|
|
@@ -903,7 +903,7 @@ module Aspera
|
|
|
903
903
|
private_key = OpenSSL::PKey::RSA.new(options.get_next_argument('private RSA key PEM value', type: String))
|
|
904
904
|
token_info = options.get_next_argument('user and group identification', type: Hash)
|
|
905
905
|
access_key = options.get_option(:username, mandatory: true)
|
|
906
|
-
return Main.result_status(
|
|
906
|
+
return Main.result_status(Api::Node.bearer_token(payload: token_info, access_key: access_key, private_key: private_key))
|
|
907
907
|
when :simulator
|
|
908
908
|
require 'aspera/node_simulator'
|
|
909
909
|
parameters = value_create_modify(command: command)
|
|
@@ -912,17 +912,12 @@ module Aspera
|
|
|
912
912
|
uri = URI.parse(parameters[:url])
|
|
913
913
|
server = WebServerSimple.new(uri, certificate: parameters[:certificate])
|
|
914
914
|
server.mount(uri.path, NodeSimulatorServlet, parameters[:credentials], transfer)
|
|
915
|
-
# on ctrl-c, tell server main loop to exit
|
|
916
|
-
trap('INT') { server.shutdown }
|
|
917
|
-
formatter.display_status("Node Simulator listening on #{uri.port}")
|
|
918
|
-
Log.log.info{"Listening on #{uri.port}"}
|
|
919
|
-
# this is blocking until server exits
|
|
920
915
|
server.start
|
|
921
916
|
return Main.result_status('Simulator terminated')
|
|
922
917
|
end # case command
|
|
923
918
|
raise 'ERROR: shall not reach this line'
|
|
924
|
-
end
|
|
925
|
-
end
|
|
926
|
-
end
|
|
927
|
-
end
|
|
928
|
-
end
|
|
919
|
+
end
|
|
920
|
+
end
|
|
921
|
+
end
|
|
922
|
+
end
|
|
923
|
+
end
|
|
@@ -9,13 +9,14 @@ require 'xmlsimple'
|
|
|
9
9
|
module Aspera
|
|
10
10
|
module Cli
|
|
11
11
|
module Plugins
|
|
12
|
-
class Orchestrator <
|
|
12
|
+
class Orchestrator < Cli::BasicAuthPlugin
|
|
13
13
|
class << self
|
|
14
14
|
STANDARD_PATH = '/aspera/orchestrator'
|
|
15
15
|
def detect(address_or_url)
|
|
16
16
|
address_or_url = "https://#{address_or_url}" unless address_or_url.match?(%r{^[a-z]{1,6}://})
|
|
17
17
|
urls = [address_or_url]
|
|
18
18
|
urls.push("#{address_or_url}#{STANDARD_PATH}") unless address_or_url.end_with?(STANDARD_PATH)
|
|
19
|
+
error = nil
|
|
19
20
|
urls.each do |base_url|
|
|
20
21
|
next unless base_url.match?('https?://')
|
|
21
22
|
api = Rest.new(base_url: base_url)
|
|
@@ -28,8 +29,10 @@ module Aspera
|
|
|
28
29
|
url: url[0..url.index(test_endpoint) - 2]
|
|
29
30
|
}
|
|
30
31
|
rescue StandardError => e
|
|
32
|
+
error = e
|
|
31
33
|
Log.log.debug{"detect error: #{e}"}
|
|
32
34
|
end
|
|
35
|
+
raise error if error
|
|
33
36
|
return nil
|
|
34
37
|
end
|
|
35
38
|
|
|
@@ -46,8 +49,8 @@ module Aspera
|
|
|
46
49
|
end
|
|
47
50
|
end
|
|
48
51
|
|
|
49
|
-
def initialize(env)
|
|
50
|
-
super
|
|
52
|
+
def initialize(**env)
|
|
53
|
+
super
|
|
51
54
|
options.declare(:result, "Specify result value as: 'work_step:parameter'")
|
|
52
55
|
options.declare(:synchronous, 'Wait for completion', values: :bool, default: :no)
|
|
53
56
|
options.declare(:ret_style, 'How return type is requested in api', values: %i[header arg ext], default: :arg)
|
|
@@ -57,24 +60,6 @@ module Aspera
|
|
|
57
60
|
|
|
58
61
|
ACTIONS = %i[health info workflow plugins processes].freeze
|
|
59
62
|
|
|
60
|
-
# for JSON format: add extension ".json" or add url parameter: format=json or Accept: application/json
|
|
61
|
-
# id can be: a parameter id=x, or at the end of url /id, for workflows: work_order[workflow_id]=wf_id
|
|
62
|
-
# def call_API_orig(endpoint,id=nil,url_params={format: :json},accept=nil)
|
|
63
|
-
# # calls are GET
|
|
64
|
-
# call_args={operation: 'GET',subpath: endpoint}
|
|
65
|
-
# # specify id if necessary
|
|
66
|
-
# call_args[:subpath]=call_args[:subpath]+'/'+id unless id.nil?
|
|
67
|
-
# unless url_params.nil?
|
|
68
|
-
# if url_params.has_key?(:format)
|
|
69
|
-
# call_args[:headers]={'Accept'=>'application/'+url_params[:format].to_s}
|
|
70
|
-
# end
|
|
71
|
-
# call_args[:headers]={'Accept'=>accept} unless accept.nil?
|
|
72
|
-
# # add params if necessary
|
|
73
|
-
# call_args[:url_params]=url_params
|
|
74
|
-
# end
|
|
75
|
-
# return @api_orch.call(call_args)
|
|
76
|
-
# end
|
|
77
|
-
|
|
78
63
|
def call_ao(endpoint, opt={})
|
|
79
64
|
opt[:prefix] = 'api' unless opt.key?(:prefix)
|
|
80
65
|
# calls are GET
|
|
@@ -91,40 +76,45 @@ module Aspera
|
|
|
91
76
|
unless format.nil?
|
|
92
77
|
case call_type
|
|
93
78
|
when :header
|
|
94
|
-
call_args[:headers] = {'Accept' =>
|
|
79
|
+
call_args[:headers] = {'Accept' => "application/#{format}" }
|
|
95
80
|
when :arg
|
|
96
81
|
call_args[:url_params] ||= {}
|
|
97
82
|
call_args[:url_params][:format] = format
|
|
98
83
|
when :ext
|
|
99
84
|
call_args[:subpath] = "#{call_args[:subpath]}.#{format}"
|
|
100
|
-
else error_unexpected_value(call_type)
|
|
85
|
+
else Aspera.error_unexpected_value(call_type)
|
|
101
86
|
end
|
|
102
87
|
end
|
|
103
|
-
result = @api_orch.call(call_args)
|
|
88
|
+
result = @api_orch.call(**call_args)
|
|
104
89
|
result[:data] = XmlSimple.xml_in(result[:http].body, opt[:xml_opt] || {'ForceArray' => true}) if format.eql?('xml')
|
|
105
90
|
Log.log.debug{Log.dump(:data, result[:data])}
|
|
106
91
|
return result
|
|
107
92
|
end
|
|
108
93
|
|
|
109
94
|
def execute_action
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
95
|
+
auth_params =
|
|
96
|
+
case options.get_option(:auth_style, mandatory: true)
|
|
97
|
+
when :arg_pass
|
|
98
|
+
{
|
|
99
|
+
type: :url,
|
|
100
|
+
url_query: {
|
|
101
|
+
'login' => options.get_option(:username, mandatory: true),
|
|
102
|
+
'password' => options.get_option(:password, mandatory: true) }
|
|
103
|
+
}
|
|
104
|
+
when :head_basic
|
|
105
|
+
{
|
|
106
|
+
type: :basic,
|
|
107
|
+
username: options.get_option(:username, mandatory: true),
|
|
108
|
+
password: options.get_option(:password, mandatory: true)
|
|
109
|
+
}
|
|
110
|
+
when :apikey
|
|
111
|
+
raise 'Not implemented'
|
|
112
|
+
end
|
|
126
113
|
|
|
127
|
-
@api_orch = Rest.new(
|
|
114
|
+
@api_orch = Rest.new(
|
|
115
|
+
base_url: options.get_option(:url, mandatory: true),
|
|
116
|
+
auth: auth_params
|
|
117
|
+
)
|
|
128
118
|
|
|
129
119
|
command1 = options.get_next_command(ACTIONS)
|
|
130
120
|
case command1
|
|
@@ -142,11 +132,11 @@ module Aspera
|
|
|
142
132
|
result = call_ao('remote_node_ping', format: 'xml', xml_opt: {'ForceArray' => false})[:data]
|
|
143
133
|
return {type: :single_object, data: result}
|
|
144
134
|
when :processes
|
|
145
|
-
# TODO:
|
|
135
|
+
# TODO: Bug ? API has only XML format
|
|
146
136
|
result = call_ao('processes_status', format: 'xml')[:data]
|
|
147
137
|
return {type: :object_list, data: result['process']}
|
|
148
138
|
when :plugins
|
|
149
|
-
# TODO:
|
|
139
|
+
# TODO: Bug ? only json format on url
|
|
150
140
|
result = call_ao('plugin_version')[:data]
|
|
151
141
|
return {type: :object_list, data: result['Plugin']}
|
|
152
142
|
when :workflow
|
|
@@ -207,7 +197,7 @@ module Aspera
|
|
|
207
197
|
result[:data] = call_ao('initiate', id: wf_id, args: call_params, accept: override_accept)[:data]
|
|
208
198
|
return result
|
|
209
199
|
end # wf command
|
|
210
|
-
else error_unexpected_value(command)
|
|
200
|
+
else Aspera.error_unexpected_value(command)
|
|
211
201
|
end # case command
|
|
212
202
|
end # execute_action
|
|
213
203
|
end # Orchestrator
|