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
|
@@ -7,9 +7,9 @@ require 'aspera/preview/options'
|
|
|
7
7
|
require 'aspera/preview/utils'
|
|
8
8
|
require 'aspera/preview/file_types'
|
|
9
9
|
require 'aspera/preview/terminal'
|
|
10
|
-
require 'aspera/
|
|
10
|
+
require 'aspera/transfer/spec'
|
|
11
11
|
require 'aspera/persistency_action_once'
|
|
12
|
-
require 'aspera/node'
|
|
12
|
+
require 'aspera/api/node'
|
|
13
13
|
require 'aspera/hash_ext'
|
|
14
14
|
require 'aspera/timer_limiter'
|
|
15
15
|
require 'aspera/id_generator'
|
|
@@ -20,7 +20,7 @@ require 'securerandom'
|
|
|
20
20
|
module Aspera
|
|
21
21
|
module Cli
|
|
22
22
|
module Plugins
|
|
23
|
-
class Preview <
|
|
23
|
+
class Preview < Cli::BasicAuthPlugin
|
|
24
24
|
# special tag to identify transfers related to generator
|
|
25
25
|
PREV_GEN_TAG = 'preview_generator'
|
|
26
26
|
# defined by node API: suffix for folder containing previews
|
|
@@ -49,8 +49,8 @@ module Aspera
|
|
|
49
49
|
attr_accessor :option_previews_folder
|
|
50
50
|
attr_accessor :option_folder_reset_cache, :option_skip_folders, :option_overwrite, :option_file_access
|
|
51
51
|
|
|
52
|
-
def initialize(env)
|
|
53
|
-
super
|
|
52
|
+
def initialize(**env)
|
|
53
|
+
super
|
|
54
54
|
@skip_types = []
|
|
55
55
|
@default_transfer_spec = nil
|
|
56
56
|
# by default generate all supported formats (clone, as altered by options)
|
|
@@ -96,7 +96,7 @@ module Aspera
|
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
options.parse_options!
|
|
99
|
-
assert_type(@option_skip_folders, Array){'skip_folder'}
|
|
99
|
+
Aspera.assert_type(@option_skip_folders, Array){'skip_folder'}
|
|
100
100
|
@tmp_folder = File.join(options.get_option(:temp_folder, mandatory: true), "#{TMP_DIR_PREFIX}.#{SecureRandom.uuid}")
|
|
101
101
|
FileUtils.mkdir_p(@tmp_folder)
|
|
102
102
|
Log.log.debug{"tmpdir: #{@tmp_folder}"}
|
|
@@ -106,7 +106,7 @@ module Aspera
|
|
|
106
106
|
@skip_types = []
|
|
107
107
|
value.split(',').each do |v|
|
|
108
108
|
s = v.to_sym
|
|
109
|
-
assert_values(s, Aspera::Preview::FileTypes::CONVERSION_TYPES){'skip_types'}
|
|
109
|
+
Aspera.assert_values(s, Aspera::Preview::FileTypes::CONVERSION_TYPES){'skip_types'}
|
|
110
110
|
@skip_types.push(s)
|
|
111
111
|
end
|
|
112
112
|
end
|
|
@@ -128,7 +128,7 @@ module Aspera
|
|
|
128
128
|
def get_folder_entries(file_id, request_args=nil)
|
|
129
129
|
headers = {'Accept' => 'application/json'}
|
|
130
130
|
headers['X-Aspera-Cache-Control'] = 'no-cache' if @option_folder_reset_cache.eql?(:header)
|
|
131
|
-
return @api_node.call(
|
|
131
|
+
return @api_node.call(operation: 'GET', subpath: "files/#{file_id}/files", headers: headers, url_params: request_args)[:data]
|
|
132
132
|
# return @api_node.read("files/#{file_id}/files",request_args)[:data]
|
|
133
133
|
end
|
|
134
134
|
|
|
@@ -153,11 +153,11 @@ module Aspera
|
|
|
153
153
|
end
|
|
154
154
|
return if events.empty?
|
|
155
155
|
events.each do |event|
|
|
156
|
-
if event['data']['direction'].eql?(
|
|
156
|
+
if event['data']['direction'].eql?(Transfer::Spec::DIRECTION_RECEIVE) &&
|
|
157
157
|
event['data']['status'].eql?('completed') &&
|
|
158
158
|
event['data']['error_code'].eql?(0) &&
|
|
159
|
-
event['data'].dig('tags',
|
|
160
|
-
folder_id = event.dig('data', 'tags',
|
|
159
|
+
event['data'].dig('tags', Transfer::Spec::TAG_RESERVED, PREV_GEN_TAG).nil?
|
|
160
|
+
folder_id = event.dig('data', 'tags', Transfer::Spec::TAG_RESERVED, 'node', 'file_id')
|
|
161
161
|
folder_id ||= event.dig('data', 'file_id')
|
|
162
162
|
if !folder_id.nil?
|
|
163
163
|
folder_entry = @api_node.read("files/#{folder_id}")[:data] rescue nil
|
|
@@ -191,7 +191,7 @@ module Aspera
|
|
|
191
191
|
if event.dig('data', 'type').eql?('file')
|
|
192
192
|
file_entry = @api_node.read("files/#{event['data']['id']}")[:data] rescue nil
|
|
193
193
|
if !file_entry.nil? &&
|
|
194
|
-
@option_skip_folders.
|
|
194
|
+
@option_skip_folders.none?{|d|file_entry['path'].start_with?(d)}
|
|
195
195
|
file_entry['parent_file_id'] = event['data']['parent_file_id']
|
|
196
196
|
if event['types'].include?('file.deleted')
|
|
197
197
|
Log.log.error('TODO'.red)
|
|
@@ -213,10 +213,10 @@ module Aspera
|
|
|
213
213
|
end
|
|
214
214
|
|
|
215
215
|
def do_transfer(direction, folder_id, source_filename, destination='/')
|
|
216
|
-
assert(!(destination.nil? && direction.eql?(
|
|
216
|
+
Aspera.assert(!(destination.nil? && direction.eql?(Transfer::Spec::DIRECTION_RECEIVE)))
|
|
217
217
|
t_spec = @api_node.transfer_spec_gen4(folder_id, direction, {
|
|
218
218
|
'paths' => [{'source' => source_filename}],
|
|
219
|
-
'tags' => {
|
|
219
|
+
'tags' => {Transfer::Spec::TAG_RESERVED => {PREV_GEN_TAG => true}}
|
|
220
220
|
})
|
|
221
221
|
# force destination, need to set this in transfer agent else it gets overwritten, not do: t_spec['destination_root']=destination
|
|
222
222
|
transfer.option_transfer_spec_deep_merge({'destination_root' => destination})
|
|
@@ -318,7 +318,7 @@ module Aspera
|
|
|
318
318
|
if @access_remote
|
|
319
319
|
raise 'missing parent_file_id in entry' if entry['parent_file_id'].nil?
|
|
320
320
|
# download original file to temp folder
|
|
321
|
-
do_transfer(
|
|
321
|
+
do_transfer(Transfer::Spec::DIRECTION_RECEIVE, entry['parent_file_id'], entry['name'], @tmp_folder)
|
|
322
322
|
end
|
|
323
323
|
Log.log.info{"source: #{entry['id']}: #{entry['path']}"}
|
|
324
324
|
gen_infos.each do |gen_info|
|
|
@@ -326,7 +326,7 @@ module Aspera
|
|
|
326
326
|
end
|
|
327
327
|
if @access_remote
|
|
328
328
|
# upload
|
|
329
|
-
do_transfer(
|
|
329
|
+
do_transfer(Transfer::Spec::DIRECTION_SEND, @previews_folder_entry['id'], local_entry_preview_dir)
|
|
330
330
|
# cleanup after upload
|
|
331
331
|
FileUtils.rm_rf(local_entry_preview_dir)
|
|
332
332
|
File.delete(File.join(@tmp_folder, entry['name']))
|
|
@@ -403,8 +403,8 @@ module Aspera
|
|
|
403
403
|
command = options.get_next_command(ACTIONS)
|
|
404
404
|
unless %i[check test show].include?(command)
|
|
405
405
|
# this will use node api
|
|
406
|
-
@api_node =
|
|
407
|
-
@transfer_server_address = URI.parse(@api_node.
|
|
406
|
+
@api_node = Api::Node.new(**basic_auth_params)
|
|
407
|
+
@transfer_server_address = URI.parse(@api_node.base_url).host
|
|
408
408
|
# get current access key
|
|
409
409
|
@access_key_self = @api_node.read('access_keys/self')[:data]
|
|
410
410
|
# TODO: check events is activated here:
|
|
@@ -422,13 +422,13 @@ module Aspera
|
|
|
422
422
|
raise Cli::Error, "Folder #{@option_previews_folder} does not exist on node. " \
|
|
423
423
|
'Please create it in the storage root, or specify an alternate name.' if @previews_folder_entry.nil?
|
|
424
424
|
else
|
|
425
|
-
assert(@access_key_self['storage']['type'].eql?('local')){'only local storage allowed in this mode'}
|
|
425
|
+
Aspera.assert(@access_key_self['storage']['type'].eql?('local')){'only local storage allowed in this mode'}
|
|
426
426
|
@local_storage_root = @access_key_self['storage']['path']
|
|
427
427
|
# TODO: option to override @local_storage_root='xxx'
|
|
428
428
|
@local_storage_root = @local_storage_root[PVCL_LOCAL_STORAGE.length..-1] if @local_storage_root.start_with?(PVCL_LOCAL_STORAGE)
|
|
429
429
|
# TODO: windows could have "C:" ?
|
|
430
|
-
assert(@local_storage_root.start_with?('/')){"not local storage: #{@local_storage_root}"}
|
|
431
|
-
assert(File.directory?(@local_storage_root), exception_class: Cli::Error){"Local storage root folder #{@local_storage_root} does not exist."}
|
|
430
|
+
Aspera.assert(@local_storage_root.start_with?('/')){"not local storage: #{@local_storage_root}"}
|
|
431
|
+
Aspera.assert(File.directory?(@local_storage_root), exception_class: Cli::Error){"Local storage root folder #{@local_storage_root} does not exist."}
|
|
432
432
|
@local_preview_folder = File.join(@local_storage_root, @option_previews_folder)
|
|
433
433
|
raise Cli::Error, "Folder #{@local_preview_folder} does not exist locally. " \
|
|
434
434
|
'Please create it, or specify an alternate name.' unless File.directory?(@local_preview_folder)
|
|
@@ -437,7 +437,7 @@ module Aspera
|
|
|
437
437
|
Log.log.debug{"marker file: #{marker_file}"}
|
|
438
438
|
if File.exist?(marker_file)
|
|
439
439
|
ak = File.read(marker_file).chomp
|
|
440
|
-
assert(@access_key_self['id'].eql?(ak)){"mismatch access key in #{marker_file}: contains #{ak}, using #{@access_key_self['id']}"}
|
|
440
|
+
Aspera.assert(@access_key_self['id'].eql?(ak)){"mismatch access key in #{marker_file}: contains #{ak}, using #{@access_key_self['id']}"}
|
|
441
441
|
else
|
|
442
442
|
File.write(marker_file, @access_key_self['id'])
|
|
443
443
|
end
|
|
@@ -461,15 +461,15 @@ module Aspera
|
|
|
461
461
|
else
|
|
462
462
|
@api_node.read("files/#{scan_id}")[:data]
|
|
463
463
|
end
|
|
464
|
-
@filter_block =
|
|
464
|
+
@filter_block = Api::Node.file_matcher_from_argument(options)
|
|
465
465
|
scan_folder_files(folder_info, scan_path)
|
|
466
466
|
return Main.result_status('scan finished')
|
|
467
467
|
when :events, :trevents
|
|
468
|
-
@filter_block =
|
|
468
|
+
@filter_block = Api::Node.file_matcher_from_argument(options)
|
|
469
469
|
iteration_persistency = nil
|
|
470
470
|
if options.get_option(:once_only, mandatory: true)
|
|
471
471
|
iteration_persistency = PersistencyActionOnce.new(
|
|
472
|
-
manager:
|
|
472
|
+
manager: persistency,
|
|
473
473
|
data: [],
|
|
474
474
|
id: IdGenerator.from_list([
|
|
475
475
|
'preview_iteration',
|
|
@@ -479,7 +479,7 @@ module Aspera
|
|
|
479
479
|
]))
|
|
480
480
|
end
|
|
481
481
|
# call processing method specified by command line command
|
|
482
|
-
send("process_#{command}", iteration_persistency)
|
|
482
|
+
send(:"process_#{command}", iteration_persistency)
|
|
483
483
|
return Main.result_status("#{command} finished")
|
|
484
484
|
when :check
|
|
485
485
|
return Main.result_status('Tools validated')
|
|
@@ -501,8 +501,8 @@ module Aspera
|
|
|
501
501
|
ensure
|
|
502
502
|
Log.log.debug{"cleaning up temp folder #{@tmp_folder}"}
|
|
503
503
|
FileUtils.rm_rf(@tmp_folder)
|
|
504
|
-
end
|
|
505
|
-
end
|
|
506
|
-
end
|
|
507
|
-
end
|
|
508
|
-
end
|
|
504
|
+
end
|
|
505
|
+
end
|
|
506
|
+
end
|
|
507
|
+
end
|
|
508
|
+
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# cspell:ignore ascmd zmode zuid zgid fasping
|
|
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/ascmd'
|
|
8
8
|
require 'aspera/ssh'
|
|
9
9
|
require 'aspera/nagios'
|
|
@@ -16,7 +16,7 @@ module Aspera
|
|
|
16
16
|
module Cli
|
|
17
17
|
module Plugins
|
|
18
18
|
# implement basic remote access with FASP/SSH
|
|
19
|
-
class Server <
|
|
19
|
+
class Server < Cli::BasicAuthPlugin
|
|
20
20
|
include SyncActions
|
|
21
21
|
SSH_SCHEME = 'ssh'
|
|
22
22
|
LOCAL_SCHEME = 'local'
|
|
@@ -53,27 +53,27 @@ module Aspera
|
|
|
53
53
|
[address_or_url]
|
|
54
54
|
else
|
|
55
55
|
[
|
|
56
|
-
"
|
|
57
|
-
"
|
|
56
|
+
"#{SSH_SCHEME}://#{address_or_url}:33001",
|
|
57
|
+
"#{SSH_SCHEME}://#{address_or_url}:22"
|
|
58
58
|
]
|
|
59
59
|
# wss not practical as it requires a token
|
|
60
60
|
end
|
|
61
|
-
|
|
61
|
+
error = nil
|
|
62
62
|
urls.each do |base_url|
|
|
63
63
|
server_uri = URI.parse(base_url)
|
|
64
64
|
Log.log.debug{"URI=#{server_uri}, host=#{server_uri.hostname}, port=#{server_uri.port}, scheme=#{server_uri.scheme}"}
|
|
65
65
|
next unless server_uri.scheme.eql?(SSH_SCHEME)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return {version: version.gsub(/^SSH-2.0-/, ''), url: base_url}
|
|
72
|
-
end
|
|
73
|
-
rescue StandardError => e
|
|
74
|
-
Log.log.debug{"detect error: #{e}"}
|
|
66
|
+
socket = TCPSocket.new(server_uri.hostname, server_uri.port)
|
|
67
|
+
socket.puts('SSH-2.0-Ascli_0.0')
|
|
68
|
+
version = socket.gets.chomp
|
|
69
|
+
if version.match?(/^SSH-2.0-/)
|
|
70
|
+
return {version: version.gsub(/^SSH-2.0-/, ''), url: base_url}
|
|
75
71
|
end
|
|
72
|
+
rescue StandardError => e
|
|
73
|
+
error = e
|
|
74
|
+
Log.log.debug{"detect error: #{e}"}
|
|
76
75
|
end
|
|
76
|
+
raise error if error
|
|
77
77
|
return nil
|
|
78
78
|
end
|
|
79
79
|
|
|
@@ -90,8 +90,8 @@ module Aspera
|
|
|
90
90
|
end
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
-
def initialize(env)
|
|
94
|
-
super
|
|
93
|
+
def initialize(**env)
|
|
94
|
+
super
|
|
95
95
|
options.declare(:ssh_keys, 'SSH key path list (Array or single)')
|
|
96
96
|
options.declare(:passphrase, 'SSH private key passphrase')
|
|
97
97
|
options.declare(:ssh_options, 'SSH options', types: Hash, default: {})
|
|
@@ -127,14 +127,14 @@ module Aspera
|
|
|
127
127
|
if !server_uri.scheme.eql?(SSH_SCHEME)
|
|
128
128
|
Log.log.warn('URL scheme is https but no token was provided in transfer spec.')
|
|
129
129
|
Log.log.warn("If you want to access the server, not using WSS for session, then use a URL with scheme \"#{SSH_SCHEME}\" and proper SSH port")
|
|
130
|
-
assumed_url = "#{SSH_SCHEME}://#{server_transfer_spec['remote_host']}:#{
|
|
130
|
+
assumed_url = "#{SSH_SCHEME}://#{server_transfer_spec['remote_host']}:#{Transfer::Spec::SSH_PORT}"
|
|
131
131
|
Log.log.warn{"Assuming proper URL is: #{assumed_url}"}
|
|
132
132
|
server_uri = URI.parse(assumed_url)
|
|
133
133
|
end
|
|
134
134
|
# Scheme is SSH
|
|
135
135
|
if options.get_option(:username).nil?
|
|
136
|
-
options.set_option(:username,
|
|
137
|
-
Log.log.info{"No username provided: Assuming default transfer user: #{
|
|
136
|
+
options.set_option(:username, Transfer::Spec::ACCESS_KEY_TRANSFER_USER)
|
|
137
|
+
Log.log.info{"No username provided: Assuming default transfer user: #{Transfer::Spec::ACCESS_KEY_TRANSFER_USER}"}
|
|
138
138
|
end
|
|
139
139
|
server_transfer_spec['remote_user'] = options.get_option(:username, mandatory: true)
|
|
140
140
|
if !server_uri.port.nil?
|
|
@@ -151,16 +151,14 @@ module Aspera
|
|
|
151
151
|
ssh_key_list = options.get_option(:ssh_keys)
|
|
152
152
|
if !ssh_key_list.nil?
|
|
153
153
|
ssh_key_list = [ssh_key_list] if ssh_key_list.is_a?(String)
|
|
154
|
-
assert_type(ssh_key_list, Array){'ssh_keys'}
|
|
155
|
-
assert(ssh_key_list.all?(String))
|
|
154
|
+
Aspera.assert_type(ssh_key_list, Array){'ssh_keys'}
|
|
155
|
+
Aspera.assert(ssh_key_list.all?(String))
|
|
156
156
|
ssh_key_list.map!{|p|File.expand_path(p)}
|
|
157
157
|
Log.log.debug{"SSH keys=#{ssh_key_list}"}
|
|
158
158
|
if !ssh_key_list.empty?
|
|
159
159
|
@ssh_opts[:keys] = ssh_key_list
|
|
160
|
-
server_transfer_spec['
|
|
161
|
-
|
|
162
|
-
Log.log.warn{"No such key file: #{k}"} unless File.exist?(k)
|
|
163
|
-
end
|
|
160
|
+
server_transfer_spec['ssh_private_key'] = File.read(ssh_key_list.first)
|
|
161
|
+
Log.log.warn{'Using only first SSH key for transfers'} unless ssh_key_list.length.eql?(1)
|
|
164
162
|
cred_set = true
|
|
165
163
|
end
|
|
166
164
|
end
|
|
@@ -178,7 +176,7 @@ module Aspera
|
|
|
178
176
|
def execute_transfer(command, transfer_spec)
|
|
179
177
|
case command
|
|
180
178
|
when :upload, :download
|
|
181
|
-
|
|
179
|
+
Transfer::Spec.action_to_direction(transfer_spec, command)
|
|
182
180
|
return Main.result_transfer(transfer.start(transfer_spec))
|
|
183
181
|
when :sync
|
|
184
182
|
# lets ignore the arguments provided by execute_sync_action, we just give the transfer spec
|
|
@@ -189,7 +187,7 @@ module Aspera
|
|
|
189
187
|
# actions without ascmd
|
|
190
188
|
BASE_ACTIONS = %i[health].concat(TRANSFER_COMMANDS).freeze
|
|
191
189
|
# all actions
|
|
192
|
-
ACTIONS = [BASE_ACTIONS,
|
|
190
|
+
ACTIONS = [BASE_ACTIONS, AsCmd::OPERATIONS, ASCMD_ALIASES.keys].flatten.freeze
|
|
193
191
|
|
|
194
192
|
def execute_action
|
|
195
193
|
server_transfer_spec = options_to_base_transfer_spec
|
|
@@ -228,16 +226,16 @@ module Aspera
|
|
|
228
226
|
else
|
|
229
227
|
nagios.add_critical('transfer', statuses.reject{|i|i.eql?(:success)}.first.to_s)
|
|
230
228
|
end
|
|
231
|
-
else error_unexpected_value(command_nagios)
|
|
229
|
+
else Aspera.error_unexpected_value(command_nagios)
|
|
232
230
|
end
|
|
233
231
|
return nagios.result
|
|
234
232
|
when *TRANSFER_COMMANDS
|
|
235
233
|
return execute_transfer(command, server_transfer_spec)
|
|
236
|
-
when *
|
|
234
|
+
when *AsCmd::OPERATIONS
|
|
237
235
|
command_arguments = options.get_next_argument('ascmd command arguments', expected: :multiple, mandatory: false)
|
|
238
|
-
ascmd =
|
|
236
|
+
ascmd = AsCmd.new(ascmd_executor)
|
|
239
237
|
begin
|
|
240
|
-
result = ascmd.
|
|
238
|
+
result = ascmd.execute_single(command, command_arguments)
|
|
241
239
|
case command
|
|
242
240
|
when :mkdir, :mv, :cp, :rm
|
|
243
241
|
return Main.result_success
|
|
@@ -248,10 +246,10 @@ module Aspera
|
|
|
248
246
|
when :du, :md5sum, :info
|
|
249
247
|
return {type: :single_object, data: result.stringify_keys}
|
|
250
248
|
end
|
|
251
|
-
rescue
|
|
249
|
+
rescue AsCmd::Error => e
|
|
252
250
|
raise Cli::BadArgument, e.extended_message
|
|
253
251
|
end
|
|
254
|
-
else error_unreachable_line
|
|
252
|
+
else Aspera.error_unreachable_line
|
|
255
253
|
end
|
|
256
254
|
end # execute_action
|
|
257
255
|
end # Server
|
|
@@ -6,7 +6,7 @@ module Aspera
|
|
|
6
6
|
module Cli
|
|
7
7
|
module Plugins
|
|
8
8
|
# Plugin for Aspera Shares v1
|
|
9
|
-
class Shares <
|
|
9
|
+
class Shares < Cli::BasicAuthPlugin
|
|
10
10
|
API_BASE = 'node_api'
|
|
11
11
|
class << self
|
|
12
12
|
def detect(address_or_url)
|
|
@@ -24,7 +24,7 @@ module Aspera
|
|
|
24
24
|
end
|
|
25
25
|
return nil unless found
|
|
26
26
|
version = 'unknown'
|
|
27
|
-
test_page = api.call(
|
|
27
|
+
test_page = api.call(operation: 'GET', subpath: 'login')
|
|
28
28
|
if (m = test_page[:http].body.match(/\(v(1\..*)\)/))
|
|
29
29
|
version = m[1]
|
|
30
30
|
end
|
|
@@ -47,8 +47,8 @@ module Aspera
|
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
def initialize(env)
|
|
51
|
-
super
|
|
50
|
+
def initialize(**env)
|
|
51
|
+
super
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
SAML_IMPORT_MANDATORY = %w[id name_id].freeze
|
|
@@ -79,7 +79,7 @@ module Aspera
|
|
|
79
79
|
when :repository, :files
|
|
80
80
|
api_shares_node = basic_auth_api(API_BASE)
|
|
81
81
|
repo_command = options.get_next_command(Node::COMMANDS_SHARES)
|
|
82
|
-
return Node.new(
|
|
82
|
+
return Node.new(**init_params, api: api_shares_node).execute_action(repo_command)
|
|
83
83
|
when :admin
|
|
84
84
|
api_shares_admin = basic_auth_api('api/v1')
|
|
85
85
|
admin_command = options.get_next_command(%i[node share transfer_settings user group].freeze)
|
|
@@ -102,17 +102,19 @@ module Aspera
|
|
|
102
102
|
when :user, :group
|
|
103
103
|
entity_type = admin_command
|
|
104
104
|
entities_location = options.get_next_command(%i[all local ldap saml])
|
|
105
|
-
|
|
105
|
+
entities_prefix = entities_location.eql?(:all) ? '' : "#{entities_location}_"
|
|
106
|
+
entities_path = "data/#{entities_prefix}#{entity_type}s"
|
|
106
107
|
entity_action = nil
|
|
107
108
|
case entities_location
|
|
108
109
|
when :all
|
|
109
|
-
entities_path = "data/#{entity_type}s"
|
|
110
110
|
entity_action = %i[list show delete]
|
|
111
111
|
entity_action.concat(USR_GRP_SETTINGS)
|
|
112
112
|
entity_action.push(:users) if entity_type.eql?(:group)
|
|
113
113
|
entity_action.freeze
|
|
114
114
|
when :local
|
|
115
|
-
entity_action = %i[list show delete create modify]
|
|
115
|
+
entity_action = %i[list show delete create modify]
|
|
116
|
+
entity_action.push(:users) if entity_type.eql?(:group)
|
|
117
|
+
entity_action.freeze
|
|
116
118
|
when :ldap
|
|
117
119
|
entity_action = %i[add].freeze
|
|
118
120
|
when :saml
|
|
@@ -131,7 +133,7 @@ module Aspera
|
|
|
131
133
|
when :import # saml
|
|
132
134
|
return do_bulk_operation(command: entity_verb, descr: 'user information') do |entity_parameters|
|
|
133
135
|
entity_parameters = entity_parameters.transform_keys{|k|k.gsub(/\s+/, '_').downcase}
|
|
134
|
-
assert_type(entity_parameters, Hash)
|
|
136
|
+
Aspera.assert_type(entity_parameters, Hash)
|
|
135
137
|
SAML_IMPORT_MANDATORY.each{|p|raise "missing mandatory field: #{p}" if entity_parameters[p].nil?}
|
|
136
138
|
entity_parameters.each_key do |p|
|
|
137
139
|
raise "unsupported field: #{p}, use: #{SAML_IMPORT_ALLOWED.join(',')}" unless SAML_IMPORT_ALLOWED.include?(p)
|
|
@@ -143,8 +145,8 @@ module Aspera
|
|
|
143
145
|
api_shares_admin.create(entities_path, {entity_type=>entity_name})[:data]
|
|
144
146
|
end
|
|
145
147
|
when :users # group
|
|
146
|
-
|
|
147
|
-
else error_unexpected_value(entity_verb)
|
|
148
|
+
return entity_action(api_shares_admin, "#{entities_path}/#{instance_identifier}/#{entities_prefix}users")
|
|
149
|
+
else Aspera.error_unexpected_value(entity_verb)
|
|
148
150
|
end
|
|
149
151
|
end
|
|
150
152
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'aspera/
|
|
3
|
+
require 'aspera/transfer/sync'
|
|
4
4
|
require 'aspera/assert'
|
|
5
5
|
|
|
6
6
|
module Aspera
|
|
@@ -8,7 +8,7 @@ module Aspera
|
|
|
8
8
|
# Module for sync actions
|
|
9
9
|
module SyncActions
|
|
10
10
|
SIMPLE_ARGUMENTS_SYNC = {
|
|
11
|
-
direction:
|
|
11
|
+
direction: Transfer::Sync::DIRECTIONS,
|
|
12
12
|
local_dir: String,
|
|
13
13
|
remote_dir: String
|
|
14
14
|
}.stringify_keys.freeze
|
|
@@ -20,7 +20,7 @@ module Aspera
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def execute_sync_action(&block)
|
|
23
|
-
assert(block){'No block given'}
|
|
23
|
+
Aspera.assert(block){'No block given'}
|
|
24
24
|
command = options.get_next_command(%i[start admin])
|
|
25
25
|
# try to get 3 arguments as simple arguments
|
|
26
26
|
case command
|
|
@@ -45,13 +45,13 @@ module Aspera
|
|
|
45
45
|
:sync_info,
|
|
46
46
|
mandatory: false,
|
|
47
47
|
default: {'sessions' => [{'name' => File.basename(simple_session_args['local_dir'])}]})
|
|
48
|
-
assert_type(async_params, Hash){'sync_info'}
|
|
49
|
-
assert_type(async_params['sessions'], Array){'sync_info[sessions]'}
|
|
50
|
-
assert_type(async_params['sessions'].first, Hash){'sync_info[sessions][0]'}
|
|
48
|
+
Aspera.assert_type(async_params, Hash){'sync_info'}
|
|
49
|
+
Aspera.assert_type(async_params['sessions'], Array){'sync_info[sessions]'}
|
|
50
|
+
Aspera.assert_type(async_params['sessions'].first, Hash){'sync_info[sessions][0]'}
|
|
51
51
|
async_params['sessions'].first.merge!(simple_session_args)
|
|
52
52
|
end
|
|
53
53
|
Log.log.debug{Log.dump('async_params', async_params)}
|
|
54
|
-
|
|
54
|
+
Transfer::Sync.start(async_params, &block)
|
|
55
55
|
return Main.result_success
|
|
56
56
|
when :admin
|
|
57
57
|
command2 = options.get_next_command([:status])
|
|
@@ -59,7 +59,7 @@ module Aspera
|
|
|
59
59
|
when :status
|
|
60
60
|
sync_session_name = options.get_next_argument('name of sync session', mandatory: false, type: String)
|
|
61
61
|
async_params = options.get_option(:sync_info, mandatory: true)
|
|
62
|
-
return {type: :single_object, data:
|
|
62
|
+
return {type: :single_object, data: Transfer::Sync.admin_status(async_params, sync_session_name)}
|
|
63
63
|
end # command2
|
|
64
64
|
end # command
|
|
65
65
|
end # execute_action
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'aspera/
|
|
4
|
-
require 'aspera/
|
|
3
|
+
require 'aspera/agent/base'
|
|
4
|
+
require 'aspera/transfer/spec'
|
|
5
5
|
require 'aspera/cli/info'
|
|
6
6
|
require 'aspera/log'
|
|
7
7
|
require 'aspera/assert'
|
|
@@ -31,7 +31,7 @@ module Aspera
|
|
|
31
31
|
:FILE_LIST_FROM_TRANSFER_SPEC,
|
|
32
32
|
:FILE_LIST_OPTIONS,
|
|
33
33
|
:DEFAULT_TRANSFER_NOTIFY_TEMPLATE
|
|
34
|
-
TRANSFER_AGENTS =
|
|
34
|
+
TRANSFER_AGENTS = Agent::Base.agent_list.freeze
|
|
35
35
|
|
|
36
36
|
class << self
|
|
37
37
|
# @return :success if all sessions statuses returned by "start" are success
|
|
@@ -55,6 +55,8 @@ module Aspera
|
|
|
55
55
|
@agent = nil
|
|
56
56
|
# source/destination pair, like "paths" of transfer spec
|
|
57
57
|
@transfer_paths = nil
|
|
58
|
+
# HTTPGW URL provided by webapp
|
|
59
|
+
@httpgw_url_lambda = nil
|
|
58
60
|
@opt_mgr.declare(:ts, 'Override transfer spec values', types: Hash, handler: {o: self, m: :option_transfer_spec})
|
|
59
61
|
@opt_mgr.declare(:to_folder, 'Destination folder for transferred files')
|
|
60
62
|
@opt_mgr.declare(:sources, "How list of transferred files is provided (#{FILE_LIST_OPTIONS.join(',')})")
|
|
@@ -68,7 +70,7 @@ module Aspera
|
|
|
68
70
|
|
|
69
71
|
# multiple option are merged
|
|
70
72
|
def option_transfer_spec=(value)
|
|
71
|
-
assert_type(value, Hash){'ts'}
|
|
73
|
+
Aspera.assert_type(value, Hash){'ts'}
|
|
72
74
|
@transfer_spec_command_line.deep_merge!(value)
|
|
73
75
|
end
|
|
74
76
|
|
|
@@ -95,11 +97,12 @@ module Aspera
|
|
|
95
97
|
end
|
|
96
98
|
|
|
97
99
|
# analyze options and create new agent if not already created or set
|
|
100
|
+
# TODO: make a Factory pattern
|
|
98
101
|
def agent_instance
|
|
99
102
|
return @agent unless @agent.nil?
|
|
100
103
|
agent_type = @opt_mgr.get_option(:transfer, mandatory: true)
|
|
101
104
|
# agent plugin is loaded on demand to avoid loading unnecessary dependencies
|
|
102
|
-
require "aspera/
|
|
105
|
+
require "aspera/agent/#{agent_type}"
|
|
103
106
|
# set keys as symbols
|
|
104
107
|
agent_options = @opt_mgr.get_option(:transfer_info).symbolize_keys
|
|
105
108
|
# special cases
|
|
@@ -113,12 +116,17 @@ module Aspera
|
|
|
113
116
|
when :direct
|
|
114
117
|
# by default do not display ascp native progress bar
|
|
115
118
|
agent_options[:quiet] = true unless agent_options.key?(:quiet)
|
|
116
|
-
agent_options[:
|
|
117
|
-
agent_options[:trusted_certs] = @config.trusted_cert_locations
|
|
119
|
+
agent_options[:check_ignore_cb] = ->(host, port){@config.ignore_cert?(host, port)}
|
|
120
|
+
agent_options[:trusted_certs] = @config.trusted_cert_locations unless agent_options.key?(:trusted_certs)
|
|
121
|
+
when :httpgw
|
|
122
|
+
unless agent_options.key?(:url) || @httpgw_url_lambda.nil?
|
|
123
|
+
Log.log.debug('retrieving HTTPGW URL from webapp')
|
|
124
|
+
agent_options[:url] = @httpgw_url_lambda.call
|
|
125
|
+
end
|
|
118
126
|
end
|
|
119
127
|
agent_options[:progress] = @config.progress_bar
|
|
120
128
|
# get agent instance
|
|
121
|
-
new_agent = Kernel.const_get("Aspera::
|
|
129
|
+
new_agent = Kernel.const_get("Aspera::Agent::#{agent_type.capitalize}").new(agent_options)
|
|
122
130
|
self.agent_instance = new_agent
|
|
123
131
|
Log.log.debug{"transfer agent is a #{@agent.class}"}
|
|
124
132
|
return @agent
|
|
@@ -135,9 +143,9 @@ module Aspera
|
|
|
135
143
|
return dest_folder unless dest_folder.nil?
|
|
136
144
|
# default: / on remote, . on local
|
|
137
145
|
case direction.to_s
|
|
138
|
-
when
|
|
139
|
-
when
|
|
140
|
-
else error_unexpected_value(direction)
|
|
146
|
+
when Transfer::Spec::DIRECTION_SEND then dest_folder = '/'
|
|
147
|
+
when Transfer::Spec::DIRECTION_RECEIVE then dest_folder = '.'
|
|
148
|
+
else Aspera.error_unexpected_value(direction)
|
|
141
149
|
end
|
|
142
150
|
return dest_folder
|
|
143
151
|
end
|
|
@@ -149,6 +157,11 @@ module Aspera
|
|
|
149
157
|
end
|
|
150
158
|
end
|
|
151
159
|
|
|
160
|
+
def httpgw_url_cb=(httpgw_url_proc)
|
|
161
|
+
Aspera.assert_type(httpgw_url_proc, Proc){'httpgw_url_cb'}
|
|
162
|
+
@httpgw_url_lambda = httpgw_url_proc
|
|
163
|
+
end
|
|
164
|
+
|
|
152
165
|
# This is how the list of files to be transferred is specified
|
|
153
166
|
# get paths suitable for transfer spec from command line
|
|
154
167
|
# @return [Hash] {source: (mandatory), destination: (optional)}
|
|
@@ -171,7 +184,7 @@ module Aspera
|
|
|
171
184
|
Log.log.debug('assume list provided in transfer spec')
|
|
172
185
|
special_case_direct_with_list =
|
|
173
186
|
@opt_mgr.get_option(:transfer, mandatory: true).eql?(:direct) &&
|
|
174
|
-
|
|
187
|
+
Transfer::Parameters.ascp_args_file_list?(@opt_mgr.get_option(:transfer_info)['ascp_args'])
|
|
175
188
|
raise Cli::BadArgument, 'transfer spec on command line must have sources' if @transfer_paths.nil? && !special_case_direct_with_list
|
|
176
189
|
# here we assume check of sources is made in transfer agent
|
|
177
190
|
return @transfer_paths
|
|
@@ -185,15 +198,15 @@ module Aspera
|
|
|
185
198
|
if !@transfer_paths.nil?
|
|
186
199
|
Log.log.warn('--sources overrides paths from --ts')
|
|
187
200
|
end
|
|
188
|
-
source_type
|
|
201
|
+
source_type = @opt_mgr.get_option(:src_type, mandatory: true)
|
|
189
202
|
case source_type
|
|
190
203
|
when :list
|
|
191
204
|
# when providing a list, just specify source
|
|
192
205
|
@transfer_paths = file_list.map{|i|{'source' => i}}
|
|
193
206
|
when :pair
|
|
194
|
-
assert(file_list.length.even?, exception_class: Cli::BadArgument){"When using pair, provide an even number of paths: #{file_list.length}"}
|
|
207
|
+
Aspera.assert(file_list.length.even?, exception_class: Cli::BadArgument){"When using pair, provide an even number of paths: #{file_list.length}"}
|
|
195
208
|
@transfer_paths = file_list.each_slice(2).to_a.map{|s, d|{'source' => s, 'destination' => d}}
|
|
196
|
-
else error_unexpected_value(source_type)
|
|
209
|
+
else Aspera.error_unexpected_value(source_type)
|
|
197
210
|
end
|
|
198
211
|
Log.log.debug{"paths=#{@transfer_paths}"}
|
|
199
212
|
return @transfer_paths
|
|
@@ -204,14 +217,14 @@ module Aspera
|
|
|
204
217
|
# @param rest_token [Rest] if oauth token regeneration supported
|
|
205
218
|
def start(transfer_spec, rest_token: nil)
|
|
206
219
|
# check parameters
|
|
207
|
-
assert_type(transfer_spec, Hash){'transfer_spec'}
|
|
220
|
+
Aspera.assert_type(transfer_spec, Hash){'transfer_spec'}
|
|
208
221
|
# process :src option
|
|
209
222
|
case transfer_spec['direction']
|
|
210
|
-
when
|
|
223
|
+
when Transfer::Spec::DIRECTION_RECEIVE
|
|
211
224
|
# init default if required in any case
|
|
212
225
|
@transfer_spec_command_line['destination_root'] ||= destination_folder(transfer_spec['direction'])
|
|
213
|
-
when
|
|
214
|
-
if transfer_spec.dig('tags',
|
|
226
|
+
when Transfer::Spec::DIRECTION_SEND
|
|
227
|
+
if transfer_spec.dig('tags', Transfer::Spec::TAG_RESERVED, 'node', 'access_key')
|
|
215
228
|
# gen4
|
|
216
229
|
@transfer_spec_command_line.delete('destination_root') if @transfer_spec_command_line.key?('destination_root_id')
|
|
217
230
|
elsif transfer_spec.key?('token')
|
|
@@ -26,7 +26,7 @@ module Aspera
|
|
|
26
26
|
|
|
27
27
|
def event(session_id:, type:, info: nil)
|
|
28
28
|
Log.log.debug{"progress: #{type} #{session_id} #{info}"}
|
|
29
|
-
assert(!session_id.nil? || type.eql?(:pre_start)){'session_id is nil'}
|
|
29
|
+
Aspera.assert(!session_id.nil? || type.eql?(:pre_start)){'session_id is nil'}
|
|
30
30
|
return if @completed
|
|
31
31
|
if @progress_bar.nil?
|
|
32
32
|
@progress_bar = ProgressBar.create(
|
data/lib/aspera/cli/version.rb
CHANGED