aspera-cli 4.9.0 → 4.11.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/BUGS.md +20 -0
- data/CHANGELOG.md +509 -0
- data/CONTRIBUTING.md +118 -0
- data/README.md +1241 -916
- data/bin/ascli +4 -4
- data/bin/asession +11 -11
- data/docs/test_env.conf +32 -21
- data/examples/aoc.rb +4 -4
- data/examples/dascli +16 -9
- data/examples/faspex4.rb +8 -8
- data/examples/node.rb +12 -12
- data/examples/server.rb +10 -10
- data/lib/aspera/aoc.rb +273 -266
- data/lib/aspera/ascmd.rb +56 -54
- data/lib/aspera/ats_api.rb +4 -4
- data/lib/aspera/cli/basic_auth_plugin.rb +15 -12
- data/lib/aspera/cli/extended_value.rb +5 -5
- data/lib/aspera/cli/formater.rb +64 -64
- data/lib/aspera/cli/info.rb +2 -2
- data/lib/aspera/cli/listener/line_dump.rb +1 -1
- data/lib/aspera/cli/listener/logger.rb +1 -1
- data/lib/aspera/cli/listener/progress.rb +5 -6
- data/lib/aspera/cli/listener/progress_multi.rb +14 -19
- data/lib/aspera/cli/main.rb +66 -67
- data/lib/aspera/cli/manager.rb +112 -110
- data/lib/aspera/cli/plugin.rb +57 -36
- data/lib/aspera/cli/plugins/alee.rb +4 -4
- data/lib/aspera/cli/plugins/aoc.rb +309 -670
- data/lib/aspera/cli/plugins/ats.rb +44 -46
- data/lib/aspera/cli/plugins/bss.rb +10 -10
- data/lib/aspera/cli/plugins/config.rb +497 -378
- data/lib/aspera/cli/plugins/console.rb +12 -12
- data/lib/aspera/cli/plugins/cos.rb +18 -20
- data/lib/aspera/cli/plugins/faspex.rb +112 -114
- data/lib/aspera/cli/plugins/faspex5.rb +71 -46
- data/lib/aspera/cli/plugins/node.rb +379 -283
- data/lib/aspera/cli/plugins/orchestrator.rb +46 -46
- data/lib/aspera/cli/plugins/preview.rb +122 -114
- data/lib/aspera/cli/plugins/server.rb +137 -83
- data/lib/aspera/cli/plugins/shares.rb +30 -29
- data/lib/aspera/cli/plugins/sync.rb +13 -33
- data/lib/aspera/cli/transfer_agent.rb +60 -59
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +3 -3
- data/lib/aspera/command_line_builder.rb +27 -27
- data/lib/aspera/cos_node.rb +22 -20
- data/lib/aspera/data_repository.rb +1 -1
- data/lib/aspera/environment.rb +35 -15
- data/lib/aspera/fasp/agent_base.rb +15 -15
- data/lib/aspera/fasp/agent_connect.rb +23 -21
- data/lib/aspera/fasp/agent_direct.rb +66 -64
- data/lib/aspera/fasp/agent_httpgw.rb +141 -78
- data/lib/aspera/fasp/agent_node.rb +23 -21
- data/lib/aspera/fasp/agent_trsdk.rb +20 -20
- data/lib/aspera/fasp/error.rb +3 -2
- data/lib/aspera/fasp/error_info.rb +11 -8
- data/lib/aspera/fasp/installation.rb +79 -79
- data/lib/aspera/fasp/listener.rb +1 -1
- data/lib/aspera/fasp/parameters.rb +86 -71
- data/lib/aspera/fasp/parameters.yaml +7 -4
- data/lib/aspera/fasp/resume_policy.rb +8 -8
- data/lib/aspera/fasp/transfer_spec.rb +35 -2
- data/lib/aspera/fasp/uri.rb +7 -7
- data/lib/aspera/faspex_gw.rb +7 -5
- data/lib/aspera/hash_ext.rb +3 -3
- data/lib/aspera/id_generator.rb +5 -5
- data/lib/aspera/keychain/encrypted_hash.rb +38 -105
- data/lib/aspera/keychain/macos_security.rb +128 -57
- data/lib/aspera/log.rb +7 -7
- data/lib/aspera/nagios.rb +19 -18
- data/lib/aspera/node.rb +209 -35
- data/lib/aspera/oauth.rb +37 -36
- data/lib/aspera/open_application.rb +19 -11
- data/lib/aspera/persistency_action_once.rb +4 -4
- data/lib/aspera/persistency_folder.rb +16 -15
- data/lib/aspera/preview/file_types.rb +8 -8
- data/lib/aspera/preview/generator.rb +67 -67
- data/lib/aspera/preview/utils.rb +27 -27
- data/lib/aspera/proxy_auto_config.js +41 -41
- data/lib/aspera/proxy_auto_config.rb +21 -14
- data/lib/aspera/rest.rb +72 -67
- data/lib/aspera/rest_call_error.rb +2 -1
- data/lib/aspera/rest_error_analyzer.rb +18 -17
- data/lib/aspera/rest_errors_aspera.rb +16 -16
- data/lib/aspera/secret_hider.rb +15 -13
- data/lib/aspera/ssh.rb +11 -10
- data/lib/aspera/sync.rb +158 -44
- data/lib/aspera/temp_file_manager.rb +2 -2
- data/lib/aspera/uri_reader.rb +4 -4
- data/lib/aspera/web_auth.rb +14 -13
- data.tar.gz.sig +0 -0
- metadata +11 -36
- metadata.gz.sig +0 -0
@@ -42,9 +42,9 @@ module Aspera
|
|
42
42
|
</default>
|
43
43
|
</CONF>
|
44
44
|
END_OF_CONFIG_FILE
|
45
|
-
DUMMY_CERT_INFO='/C=US/ST=California/L=Emeryville/O=Aspera Inc./OU=Corporate/CN=Aspera Inc./emailAddress=info@asperasoft.com'
|
46
|
-
private_constant :PRODUCT_CONNECT
|
47
|
-
:ONE_YEAR_SECONDS
|
45
|
+
DUMMY_CERT_INFO = '/C=US/ST=California/L=Emeryville/O=Aspera Inc./OU=Corporate/CN=Aspera Inc./emailAddress=info@asperasoft.com'
|
46
|
+
private_constant :PRODUCT_CONNECT, :PRODUCT_CLI_V1, :PRODUCT_DRIVE, :PRODUCT_ENTSRV, :EXT_RUBY_PROTOBUF, :RB_SDK_FOLDER,
|
47
|
+
:ONE_YEAR_SECONDS, :DEFAULT_ASPERA_CONF, :DUMMY_CERT_INFO
|
48
48
|
# set ascp executable path
|
49
49
|
def ascp_path=(v)
|
50
50
|
@path_to_ascp = v
|
@@ -55,7 +55,7 @@ module Aspera
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def sdk_ruby_folder
|
58
|
-
ruby_pb_folder = File.join(sdk_folder,RB_SDK_FOLDER)
|
58
|
+
ruby_pb_folder = File.join(sdk_folder, RB_SDK_FOLDER)
|
59
59
|
FileUtils.mkdir_p(ruby_pb_folder) unless Dir.exist?(ruby_pb_folder)
|
60
60
|
return ruby_pb_folder
|
61
61
|
end
|
@@ -87,7 +87,7 @@ module Aspera
|
|
87
87
|
raise "no such product installed: #{product_name}" if pl.nil?
|
88
88
|
end
|
89
89
|
self.ascp_path = pl[:ascp_path]
|
90
|
-
Log.log.debug
|
90
|
+
Log.log.debug{"ascp_path=#{@path_to_ascp}"}
|
91
91
|
end
|
92
92
|
|
93
93
|
# @return the list of installed products in format of product_locations
|
@@ -104,15 +104,15 @@ module Aspera
|
|
104
104
|
@found_products = scan_locations.select! do |item|
|
105
105
|
# skip if not main folder
|
106
106
|
next false unless Dir.exist?(item[:app_root])
|
107
|
-
Log.log.debug
|
107
|
+
Log.log.debug{"Found #{item[:app_root]}"}
|
108
108
|
sub_bin = item[:sub_bin] || BIN_SUBFOLDER
|
109
|
-
item[:ascp_path] = File.join(item[:app_root],sub_bin,ascp_filename)
|
109
|
+
item[:ascp_path] = File.join(item[:app_root], sub_bin, ascp_filename)
|
110
110
|
# skip if no ascp
|
111
111
|
next false unless File.exist?(item[:ascp_path])
|
112
112
|
# read info from product info file if present
|
113
113
|
product_info_file = "#{item[:app_root]}/#{PRODUCT_INFO}"
|
114
114
|
if File.exist?(product_info_file)
|
115
|
-
res_s = XmlSimple.xml_in(File.read(product_info_file),{'ForceArray' => false})
|
115
|
+
res_s = XmlSimple.xml_in(File.read(product_info_file), {'ForceArray' => false})
|
116
116
|
item[:name] = res_s['name']
|
117
117
|
item[:version] = res_s['version']
|
118
118
|
else
|
@@ -131,20 +131,20 @@ module Aspera
|
|
131
131
|
# keys and certs are generated locally... (they are well known values, arch. independant)
|
132
132
|
def path(k)
|
133
133
|
case k
|
134
|
-
when :ascp
|
134
|
+
when :ascp, :ascp4
|
135
135
|
use_ascp_from_product(FIRST_FOUND) if @path_to_ascp.nil?
|
136
136
|
file = @path_to_ascp
|
137
|
-
#
|
138
|
-
file = file.gsub('ascp','ascp4') if k.eql?(:ascp4)
|
137
|
+
# NOTE: that there might be a .exe at the end
|
138
|
+
file = file.gsub('ascp', 'ascp4') if k.eql?(:ascp4)
|
139
139
|
when :transferd
|
140
140
|
file = transferd_filepath
|
141
141
|
when :ssh_bypass_key_dsa
|
142
|
-
file=Environment.write_file_restricted(File.join(sdk_folder,'aspera_bypass_dsa.pem')) {get_key('dsa',1)}
|
142
|
+
file = Environment.write_file_restricted(File.join(sdk_folder, 'aspera_bypass_dsa.pem')) {get_key('dsa', 1)}
|
143
143
|
when :ssh_bypass_key_rsa
|
144
|
-
file=Environment.write_file_restricted(File.join(sdk_folder,'aspera_bypass_rsa.pem')) {get_key('rsa',2)}
|
144
|
+
file = Environment.write_file_restricted(File.join(sdk_folder, 'aspera_bypass_rsa.pem')) {get_key('rsa', 2)}
|
145
145
|
when :aspera_license
|
146
|
-
file=Environment.write_file_restricted(File.join(sdk_folder,'aspera-license')) do
|
147
|
-
clear=[
|
146
|
+
file = Environment.write_file_restricted(File.join(sdk_folder, 'aspera-license')) do
|
147
|
+
clear = [
|
148
148
|
Zlib::Inflate.inflate(DataRepository.instance.data(6)),
|
149
149
|
"==SIGNATURE==\n",
|
150
150
|
Base64.strict_encode64(DataRepository.instance.data(7))
|
@@ -152,10 +152,10 @@ module Aspera
|
|
152
152
|
Base64.strict_encode64(clear.join)
|
153
153
|
end
|
154
154
|
when :aspera_conf
|
155
|
-
file=Environment.write_file_restricted(File.join(sdk_folder,'aspera.conf')) {DEFAULT_ASPERA_CONF}
|
156
|
-
when :fallback_cert
|
157
|
-
file_key = File.join(sdk_folder,'aspera_fallback_key.pem')
|
158
|
-
file_cert = File.join(sdk_folder,'aspera_fallback_cert.pem')
|
155
|
+
file = Environment.write_file_restricted(File.join(sdk_folder, 'aspera.conf')) {DEFAULT_ASPERA_CONF}
|
156
|
+
when :fallback_cert, :fallback_key
|
157
|
+
file_key = File.join(sdk_folder, 'aspera_fallback_key.pem')
|
158
|
+
file_cert = File.join(sdk_folder, 'aspera_fallback_cert.pem')
|
159
159
|
if !File.exist?(file_key) || !File.exist?(file_cert)
|
160
160
|
require 'openssl'
|
161
161
|
# create new self signed certificate for http fallback
|
@@ -182,10 +182,10 @@ module Aspera
|
|
182
182
|
# @return the file path of local connect where API's URI can be read
|
183
183
|
def connect_uri
|
184
184
|
connect = get_product_folders(PRODUCT_CONNECT)
|
185
|
-
folder = File.join(connect[:run_root],VARRUN_SUBFOLDER)
|
186
|
-
['','s'].each do |ext|
|
187
|
-
uri_file = File.join(folder,"http#{ext}.uri")
|
188
|
-
Log.log.debug
|
185
|
+
folder = File.join(connect[:run_root], VARRUN_SUBFOLDER)
|
186
|
+
['', 's'].each do |ext|
|
187
|
+
uri_file = File.join(folder, "http#{ext}.uri")
|
188
|
+
Log.log.debug{"checking connect port file: #{uri_file}"}
|
189
189
|
if File.exist?(uri_file)
|
190
190
|
return File.open(uri_file, &:gets).strip
|
191
191
|
end
|
@@ -196,12 +196,12 @@ module Aspera
|
|
196
196
|
# @ return path to configuration file of aspera CLI
|
197
197
|
def cli_conf_file
|
198
198
|
connect = get_product_folders(PRODUCT_CLI_V1)
|
199
|
-
return File.join(connect[:app_root],BIN_SUBFOLDER,'.aspera_cli_conf')
|
199
|
+
return File.join(connect[:app_root], BIN_SUBFOLDER, '.aspera_cli_conf')
|
200
200
|
end
|
201
201
|
|
202
202
|
# default bypass key phrase
|
203
203
|
def bypass_pass
|
204
|
-
return format('%08x-%04x-%04x-%04x-%04x%08x'
|
204
|
+
return format('%08x-%04x-%04x-%04x-%04x%08x', *DataRepository.instance.data(3).unpack('NnnnnN'))
|
205
205
|
end
|
206
206
|
|
207
207
|
def bypass_keys
|
@@ -210,16 +210,16 @@ module Aspera
|
|
210
210
|
|
211
211
|
# use in plugin `config`
|
212
212
|
def get_ascp_version(exe_path)
|
213
|
-
return get_exe_version(exe_path,'-A')
|
213
|
+
return get_exe_version(exe_path, '-A')
|
214
214
|
end
|
215
215
|
|
216
216
|
# Check that specified path is ascp and get version
|
217
|
-
def get_exe_version(exe_path,vers_arg)
|
217
|
+
def get_exe_version(exe_path, vers_arg)
|
218
218
|
raise 'ERROR: nil arg' if exe_path.nil?
|
219
219
|
return nil unless File.exist?(exe_path)
|
220
220
|
exe_version = nil
|
221
221
|
cmd_out = %x("#{exe_path}" #{vers_arg})
|
222
|
-
raise "An error
|
222
|
+
raise "An error occurred when testing #{ascp_filename}: #{cmd_out}" unless $CHILD_STATUS == 0
|
223
223
|
# get version from ascp, only after full extract, as windows requires DLLs (SSL/TLS/etc...)
|
224
224
|
m = cmd_out.match(/ version ([0-9.]+)/)
|
225
225
|
exe_version = m[1] unless m.nil?
|
@@ -233,18 +233,18 @@ module Aspera
|
|
233
233
|
# SDK is organized by architecture, check this first, in case architecture is not supported
|
234
234
|
arch_filter = "#{Environment.architecture}/"
|
235
235
|
require 'zip'
|
236
|
-
sdk_zip_path = File.join(Dir.tmpdir,'sdk.zip')
|
236
|
+
sdk_zip_path = File.join(Dir.tmpdir, 'sdk.zip')
|
237
237
|
if sdk_url.start_with?('file:')
|
238
238
|
# require specific file scheme: the path part is "relative", or absolute if there are 4 slash
|
239
239
|
raise 'use format: file:///<path>' unless sdk_url.start_with?('file:///')
|
240
|
-
sdk_zip_path = sdk_url.gsub(%r{^file:///},'')
|
240
|
+
sdk_zip_path = sdk_url.gsub(%r{^file:///}, '')
|
241
241
|
else
|
242
|
-
Aspera::Rest.new(base_url: sdk_url, redirect_max: 3).call(operation: 'GET',save_to_file: sdk_zip_path)
|
242
|
+
Aspera::Rest.new(base_url: sdk_url, redirect_max: 3).call(operation: 'GET', save_to_file: sdk_zip_path)
|
243
243
|
end
|
244
244
|
# rename old install
|
245
245
|
if !Dir.empty?(sdk_folder)
|
246
246
|
Log.log.warn('Previous install exists, renaming folder.')
|
247
|
-
File.rename(sdk_folder,"#{sdk_folder}.#{Time.now.strftime('%Y%m%d%H%M%S')}")
|
247
|
+
File.rename(sdk_folder, "#{sdk_folder}.#{Time.now.strftime('%Y%m%d%H%M%S')}")
|
248
248
|
# TODO: delete old archives ?
|
249
249
|
end
|
250
250
|
# extract files from archive
|
@@ -258,7 +258,7 @@ module Aspera
|
|
258
258
|
# ruby adapters
|
259
259
|
dest_folder = sdk_ruby_folder if entry.name.end_with?(EXT_RUBY_PROTOBUF)
|
260
260
|
next if dest_folder.nil?
|
261
|
-
File.open(File.join(dest_folder,File.basename(entry.name)), 'wb') do |output_stream|
|
261
|
+
File.open(File.join(dest_folder, File.basename(entry.name)), 'wb') do |output_stream|
|
262
262
|
IO.copy_stream(entry.get_input_stream, output_stream)
|
263
263
|
end
|
264
264
|
end
|
@@ -267,17 +267,17 @@ module Aspera
|
|
267
267
|
# ensure license file are generated so that ascp invokation for version works
|
268
268
|
path(:aspera_license)
|
269
269
|
path(:aspera_conf)
|
270
|
-
ascp_path = File.join(sdk_folder,ascp_filename)
|
270
|
+
ascp_path = File.join(sdk_folder, ascp_filename)
|
271
271
|
raise "No #{ascp_filename} found in SDK archive" unless File.exist?(ascp_path)
|
272
|
-
|
273
|
-
|
274
|
-
ascp_version = get_ascp_version(File.join(sdk_folder,ascp_filename))
|
272
|
+
Environment.restrict_file_access(ascp_path, mode: 0o755)
|
273
|
+
Environment.restrict_file_access(ascp_path.gsub('ascp', 'ascp4'), mode: 0o755)
|
274
|
+
ascp_version = get_ascp_version(File.join(sdk_folder, ascp_filename))
|
275
275
|
trd_path = transferd_filepath
|
276
|
-
Log.log.warn
|
277
|
-
|
278
|
-
transferd_version = get_exe_version(trd_path,'version')
|
276
|
+
Log.log.warn{"No #{trd_path} in SDK archive"} unless File.exist?(trd_path)
|
277
|
+
Environment.restrict_file_access(trd_path, mode: 0o755) if File.exist?(trd_path)
|
278
|
+
transferd_version = get_exe_version(trd_path, 'version')
|
279
279
|
sdk_version = transferd_version || ascp_version
|
280
|
-
File.write(File.join(sdk_folder,PRODUCT_INFO),"<product><name>IBM Aspera SDK</name><version>#{sdk_version}</version></product>")
|
280
|
+
File.write(File.join(sdk_folder, PRODUCT_INFO), "<product><name>IBM Aspera SDK</name><version>#{sdk_version}</version></product>")
|
281
281
|
return sdk_version
|
282
282
|
end
|
283
283
|
|
@@ -285,13 +285,13 @@ module Aspera
|
|
285
285
|
|
286
286
|
BIN_SUBFOLDER = 'bin'
|
287
287
|
ETC_SUBFOLDER = 'etc'
|
288
|
-
VARRUN_SUBFOLDER = File.join('var','run')
|
288
|
+
VARRUN_SUBFOLDER = File.join('var', 'run')
|
289
289
|
# product information manifest: XML (part of aspera product)
|
290
290
|
PRODUCT_INFO = 'product-info.mf'
|
291
291
|
# policy for product selection
|
292
292
|
FIRST_FOUND = 'FIRST'
|
293
293
|
|
294
|
-
private_constant :BIN_SUBFOLDER
|
294
|
+
private_constant :BIN_SUBFOLDER, :ETC_SUBFOLDER, :VARRUN_SUBFOLDER, :PRODUCT_INFO
|
295
295
|
|
296
296
|
def initialize
|
297
297
|
@path_to_ascp = nil
|
@@ -313,7 +313,7 @@ module Aspera
|
|
313
313
|
end
|
314
314
|
|
315
315
|
def transferd_filepath
|
316
|
-
return File.join(sdk_folder,'asperatransferd' + Environment.exe_extension)
|
316
|
+
return File.join(sdk_folder, 'asperatransferd' + Environment.exe_extension)
|
317
317
|
end
|
318
318
|
|
319
319
|
# @return product folders depending on OS fields
|
@@ -326,54 +326,54 @@ module Aspera
|
|
326
326
|
case Aspera::Environment.os
|
327
327
|
when Aspera::Environment::OS_WINDOWS; return [{
|
328
328
|
expected: PRODUCT_CONNECT,
|
329
|
-
app_root: File.join(ENV['LOCALAPPDATA'],'Programs','Aspera','Aspera Connect'),
|
330
|
-
log_root: File.join(ENV['LOCALAPPDATA'],'Aspera','Aspera Connect','var','log'),
|
331
|
-
run_root: File.join(ENV['LOCALAPPDATA'],'Aspera','Aspera Connect')
|
332
|
-
},{
|
329
|
+
app_root: File.join(ENV['LOCALAPPDATA'], 'Programs', 'Aspera', 'Aspera Connect'),
|
330
|
+
log_root: File.join(ENV['LOCALAPPDATA'], 'Aspera', 'Aspera Connect', 'var', 'log'),
|
331
|
+
run_root: File.join(ENV['LOCALAPPDATA'], 'Aspera', 'Aspera Connect')
|
332
|
+
}, {
|
333
333
|
expected: PRODUCT_CLI_V1,
|
334
|
-
app_root: File.join('C:','Program Files','Aspera','cli'),
|
335
|
-
log_root: File.join('C:','Program Files','Aspera','cli','var','log')
|
336
|
-
},{
|
334
|
+
app_root: File.join('C:', 'Program Files', 'Aspera', 'cli'),
|
335
|
+
log_root: File.join('C:', 'Program Files', 'Aspera', 'cli', 'var', 'log')
|
336
|
+
}, {
|
337
337
|
expected: PRODUCT_ENTSRV,
|
338
|
-
app_root: File.join('C:','Program Files','Aspera','Enterprise Server'),
|
339
|
-
log_root: File.join('C:','Program Files','Aspera','Enterprise Server','var','log')
|
338
|
+
app_root: File.join('C:', 'Program Files', 'Aspera', 'Enterprise Server'),
|
339
|
+
log_root: File.join('C:', 'Program Files', 'Aspera', 'Enterprise Server', 'var', 'log')
|
340
340
|
}]
|
341
341
|
when Aspera::Environment::OS_X; return [{
|
342
342
|
expected: PRODUCT_CONNECT,
|
343
|
-
app_root: File.join(Dir.home,'Applications','Aspera Connect.app'),
|
344
|
-
log_root: File.join(Dir.home,'Library','Logs','Aspera_Connect'),
|
345
|
-
run_root: File.join(Dir.home,'Library','Application Support','Aspera','Aspera Connect'),
|
346
|
-
sub_bin: File.join('Contents','Resources')
|
347
|
-
},{
|
343
|
+
app_root: File.join(Dir.home, 'Applications', 'Aspera Connect.app'),
|
344
|
+
log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera_Connect'),
|
345
|
+
run_root: File.join(Dir.home, 'Library', 'Application Support', 'Aspera', 'Aspera Connect'),
|
346
|
+
sub_bin: File.join('Contents', 'Resources')
|
347
|
+
}, {
|
348
348
|
expected: PRODUCT_CONNECT,
|
349
|
-
app_root: File.join('','Applications','Aspera Connect.app'),
|
350
|
-
log_root: File.join(Dir.home,'Library','Logs','Aspera_Connect'),
|
351
|
-
run_root: File.join(Dir.home,'Library','Application Support','Aspera','Aspera Connect'),
|
352
|
-
sub_bin: File.join('Contents','Resources')
|
353
|
-
},{
|
349
|
+
app_root: File.join('', 'Applications', 'Aspera Connect.app'),
|
350
|
+
log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera_Connect'),
|
351
|
+
run_root: File.join(Dir.home, 'Library', 'Application Support', 'Aspera', 'Aspera Connect'),
|
352
|
+
sub_bin: File.join('Contents', 'Resources')
|
353
|
+
}, {
|
354
354
|
expected: PRODUCT_CLI_V1,
|
355
|
-
app_root: File.join(Dir.home,'Applications','Aspera CLI'),
|
356
|
-
log_root: File.join(Dir.home,'Library','Logs','Aspera')
|
357
|
-
},{
|
355
|
+
app_root: File.join(Dir.home, 'Applications', 'Aspera CLI'),
|
356
|
+
log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera')
|
357
|
+
}, {
|
358
358
|
expected: PRODUCT_ENTSRV,
|
359
|
-
app_root: File.join('','Library','Aspera'),
|
360
|
-
log_root: File.join(Dir.home,'Library','Logs','Aspera')
|
361
|
-
},{
|
359
|
+
app_root: File.join('', 'Library', 'Aspera'),
|
360
|
+
log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera')
|
361
|
+
}, {
|
362
362
|
expected: PRODUCT_DRIVE,
|
363
|
-
app_root: File.join('','Applications','Aspera Drive.app'),
|
364
|
-
log_root: File.join(Dir.home,'Library','Logs','Aspera_Drive'),
|
365
|
-
sub_bin: File.join('Contents','Resources')
|
363
|
+
app_root: File.join('', 'Applications', 'Aspera Drive.app'),
|
364
|
+
log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera_Drive'),
|
365
|
+
sub_bin: File.join('Contents', 'Resources')
|
366
366
|
}]
|
367
367
|
else; return [{ # other: Linux and Unix family
|
368
368
|
expected: PRODUCT_CONNECT,
|
369
|
-
app_root: File.join(Dir.home,'.aspera','connect'),
|
370
|
-
run_root: File.join(Dir.home,'.aspera','connect')
|
371
|
-
},{
|
369
|
+
app_root: File.join(Dir.home, '.aspera', 'connect'),
|
370
|
+
run_root: File.join(Dir.home, '.aspera', 'connect')
|
371
|
+
}, {
|
372
372
|
expected: PRODUCT_CLI_V1,
|
373
|
-
app_root: File.join(Dir.home,'.aspera','cli')
|
374
|
-
},{
|
373
|
+
app_root: File.join(Dir.home, '.aspera', 'cli')
|
374
|
+
}, {
|
375
375
|
expected: PRODUCT_ENTSRV,
|
376
|
-
app_root: File.join('','opt','aspera')
|
376
|
+
app_root: File.join('', 'opt', 'aspera')
|
377
377
|
}]
|
378
378
|
end
|
379
379
|
end
|
@@ -381,7 +381,7 @@ module Aspera
|
|
381
381
|
# @return a standard bypass key
|
382
382
|
# @param type rsa or dsa
|
383
383
|
# @param id in repository 1 for dsa, 2 for rsa
|
384
|
-
def get_key(type,id)
|
384
|
+
def get_key(type, id)
|
385
385
|
# generate PEM from DER
|
386
386
|
OpenSSL::PKey.const_get(type.upcase).new(DataRepository.instance.data(id)).to_pem
|
387
387
|
end
|
data/lib/aspera/fasp/listener.rb
CHANGED
@@ -31,39 +31,52 @@ module Aspera
|
|
31
31
|
def description
|
32
32
|
if @param_description_cache.nil?
|
33
33
|
# config file in same folder with same name as this source
|
34
|
-
description_from_yaml=YAML.load_file("#{__FILE__[0..-3]}yaml")
|
34
|
+
description_from_yaml = YAML.load_file("#{__FILE__[0..-3]}yaml")
|
35
35
|
@param_description_cache = Aspera::CommandLineBuilder.normalize_description(description_from_yaml)
|
36
36
|
end
|
37
37
|
return @param_description_cache
|
38
38
|
end
|
39
39
|
|
40
40
|
# @return a table suitable to display in manual
|
41
|
-
def man_table
|
41
|
+
def man_table(to_text: true)
|
42
42
|
result = []
|
43
|
-
description.each do |k,i|
|
44
|
-
param = {name: k, type: [i[:accepted_types]].flatten.join(','),description: i[:desc]}
|
43
|
+
description.each do |k, i|
|
44
|
+
param = {name: k, type: [i[:accepted_types]].flatten.join(','), description: i[:desc]}
|
45
45
|
# add flags for supported agents in doc
|
46
46
|
SUPPORTED_AGENTS.each do |a|
|
47
47
|
param[a.to_s[0].to_sym] = i[:tragents].nil? || i[:tragents].include?(a) ? 'Y' : ''
|
48
48
|
end
|
49
49
|
# only keep lines that are usable in supported agents
|
50
|
-
next if SUPPORTED_AGENTS_SHORT.inject(true){|m,j|m && param[j].empty?}
|
50
|
+
next if SUPPORTED_AGENTS_SHORT.inject(true){|m, j|m && param[j].empty?}
|
51
51
|
param[:cli] =
|
52
52
|
case i[:cltype]
|
53
53
|
when :envvar then 'env:' + i[:clvarname]
|
54
|
-
when :opt_without_arg
|
54
|
+
when :opt_without_arg then i[:clswitch]
|
55
|
+
when :opt_with_arg
|
56
|
+
values = if i.key?(:enum)
|
57
|
+
['enum']
|
58
|
+
elsif i[:accepted_types].is_a?(Array)
|
59
|
+
i[:accepted_types]
|
60
|
+
elsif !i[:accepted_types].nil?
|
61
|
+
[i[:accepted_types]]
|
62
|
+
else
|
63
|
+
raise "error: #{param}"
|
64
|
+
end.map{|n|"{#{n}}"}.join('|')
|
65
|
+
conv = i.key?(:clconvert) ? '(conversion)' : ''
|
66
|
+
"#{i[:clswitch]} #{conv}#{values}"
|
55
67
|
else ''
|
56
68
|
end
|
57
|
-
if i.
|
69
|
+
if i.key?(:enum)
|
58
70
|
param[:description] += "\nAllowed values: #{i[:enum].join(', ')}"
|
59
71
|
end
|
72
|
+
param[:description] = param[:description].gsub('/', '/') if to_text
|
60
73
|
result.push(param)
|
61
74
|
end
|
62
75
|
return result
|
63
76
|
end
|
64
77
|
|
65
78
|
# special encoding methods used in YAML (key: :clconvert)
|
66
|
-
def clconv_remove_hyphen(v); v.tr('-',''); end
|
79
|
+
def clconv_remove_hyphen(v); v.tr('-', ''); end
|
67
80
|
|
68
81
|
# special encoding methods used in YAML (key: :clconvert)
|
69
82
|
def clconv_json64(v); Base64.strict_encode64(JSON.generate(v)); end
|
@@ -73,13 +86,13 @@ module Aspera
|
|
73
86
|
|
74
87
|
# file list is provided directly with ascp arguments
|
75
88
|
def ts_has_ascp_file_list(ts)
|
76
|
-
(ts['EX_ascp_args'].is_a?(Array) && ['--file-list','--file-pair-list'].any?{|i|ts['EX_ascp_args'].include?(i)}) ||
|
77
|
-
|
78
|
-
|
89
|
+
(ts['EX_ascp_args'].is_a?(Array) && ['--file-list', '--file-pair-list'].any?{|i|ts['EX_ascp_args'].include?(i)}) ||
|
90
|
+
ts.key?('EX_file_list') ||
|
91
|
+
ts.key?('EX_file_pair_list')
|
79
92
|
end
|
80
93
|
|
81
|
-
def ts_to_env_args(transfer_spec,options)
|
82
|
-
return Parameters.new(transfer_spec,options).ascp_args
|
94
|
+
def ts_to_env_args(transfer_spec, options)
|
95
|
+
return Parameters.new(transfer_spec, options).ascp_args
|
83
96
|
end
|
84
97
|
|
85
98
|
# temp file list files are created here
|
@@ -95,11 +108,56 @@ module Aspera
|
|
95
108
|
end # self
|
96
109
|
|
97
110
|
# @param options [Hash] key: :wss: bool
|
98
|
-
def initialize(job_spec,options)
|
111
|
+
def initialize(job_spec, options)
|
99
112
|
@job_spec = job_spec
|
100
113
|
@options = options
|
101
|
-
@builder = Aspera::CommandLineBuilder.new(@job_spec,self.class.description)
|
102
|
-
Log.log.debug
|
114
|
+
@builder = Aspera::CommandLineBuilder.new(@job_spec, self.class.description)
|
115
|
+
Log.log.debug{"agent options: #{@options}"}
|
116
|
+
end
|
117
|
+
|
118
|
+
def process_file_list
|
119
|
+
# is the file list provided through EX_ parameters?
|
120
|
+
ascp_file_list_provided = self.class.ts_has_ascp_file_list(@job_spec)
|
121
|
+
# set if paths is mandatory in ts
|
122
|
+
@builder.params_definition['paths'][:mandatory] = !@job_spec.key?('keepalive') && !ascp_file_list_provided
|
123
|
+
# get paths in transfer spec (after setting if it is mandatory)
|
124
|
+
ts_paths_array = @builder.process_param('paths', :get_value)
|
125
|
+
if ascp_file_list_provided && !ts_paths_array.nil?
|
126
|
+
raise 'file list provided both in transfer spec and ascp file list. Remove one of them.'
|
127
|
+
end
|
128
|
+
# option 1: EX_file_list
|
129
|
+
file_list_file = @builder.process_param('EX_file_list', :get_value)
|
130
|
+
if file_list_file.nil?
|
131
|
+
# option 2: EX_file_pair_list
|
132
|
+
file_list_file = @builder.process_param('EX_file_pair_list', :get_value)
|
133
|
+
if !file_list_file.nil?
|
134
|
+
option = '--file-pair-list'
|
135
|
+
elsif !ts_paths_array.nil?
|
136
|
+
# option 3: in TS, it is an array
|
137
|
+
if self.class.file_list_folder.nil?
|
138
|
+
# not safe for special characters ? (maybe not, depends on OS)
|
139
|
+
Log.log.debug('placing source file list on command line (no file list file)')
|
140
|
+
@builder.add_command_line_options(ts_paths_array.map{|i|i['source']})
|
141
|
+
else
|
142
|
+
# safer option: generate a file list file if there is storage defined for it
|
143
|
+
# if there is destination in paths, then use filepairlist
|
144
|
+
# TODO: well, we test only the first one, but anyway it shall be consistent
|
145
|
+
if ts_paths_array.first.key?('destination')
|
146
|
+
option = '--file-pair-list'
|
147
|
+
lines = ts_paths_array.each_with_object([]){|e, m|m.push(e['source'], e['destination']); }
|
148
|
+
else
|
149
|
+
option = '--file-list'
|
150
|
+
lines = ts_paths_array.map{|i|i['source']}
|
151
|
+
end
|
152
|
+
file_list_file = Aspera::TempFileManager.instance.new_file_path_in_folder(self.class.file_list_folder)
|
153
|
+
File.write(file_list_file, lines.join("\n"))
|
154
|
+
Log.log.debug{"#{option}=\n#{File.read(file_list_file)}".red}
|
155
|
+
end
|
156
|
+
end
|
157
|
+
else
|
158
|
+
option = '--file-list'
|
159
|
+
end
|
160
|
+
@builder.add_command_line_options(["#{option}=#{file_list_file}"]) unless option.nil?
|
103
161
|
end
|
104
162
|
|
105
163
|
# translate transfer spec to env vars and command line arguments for ascp
|
@@ -111,22 +169,22 @@ module Aspera
|
|
111
169
|
ascp_version: :ascp
|
112
170
|
}
|
113
171
|
# some ssh credentials are required to avoid interactive password input
|
114
|
-
if !@job_spec.
|
115
|
-
|
116
|
-
|
172
|
+
if !@job_spec.key?('remote_password') &&
|
173
|
+
!@job_spec.key?('ssh_private_key') &&
|
174
|
+
!@job_spec.key?('EX_ssh_key_paths')
|
117
175
|
raise Fasp::Error, 'required: password or ssh key (value or path)'
|
118
176
|
end
|
119
177
|
|
120
178
|
# special cases
|
121
|
-
@job_spec.delete('source_root') if @job_spec.
|
179
|
+
@job_spec.delete('source_root') if @job_spec.key?('source_root') && @job_spec['source_root'].empty?
|
122
180
|
|
123
181
|
# use web socket session initiation ?
|
124
|
-
if @builder.process_param('wss_enabled'
|
182
|
+
if @builder.process_param('wss_enabled', :get_value) && (@options[:wss] || !@job_spec.key?('fasp_port'))
|
125
183
|
# by default use web socket session if available, unless removed by user
|
126
184
|
@builder.add_command_line_options(['--ws-connect'])
|
127
185
|
# TODO: option to give order ssh,ws (legacy http is implied bu ssh)
|
128
186
|
# quel bordel:
|
129
|
-
@job_spec['ssh_port'] = @builder.process_param('wss_port'
|
187
|
+
@job_spec['ssh_port'] = @builder.process_param('wss_port', :get_value)
|
130
188
|
@job_spec.delete('fasp_port')
|
131
189
|
@job_spec.delete('EX_ssh_key_paths')
|
132
190
|
@job_spec.delete('sshfp')
|
@@ -142,68 +200,25 @@ module Aspera
|
|
142
200
|
@builder.process_params
|
143
201
|
|
144
202
|
# symbol must be index of Installation.paths
|
145
|
-
if @builder.process_param('use_ascp4'
|
203
|
+
if @builder.process_param('use_ascp4', :get_value)
|
146
204
|
env_args[:ascp_version] = :ascp4
|
147
205
|
else
|
148
206
|
env_args[:ascp_version] = :ascp
|
149
207
|
# destination will be base64 encoded, put before path arguments
|
150
208
|
@builder.add_command_line_options(['--dest64'])
|
151
209
|
end
|
152
|
-
#
|
153
|
-
|
154
|
-
# is the file list provided through EX_ parameters?
|
155
|
-
ascp_file_list_provided = self.class.ts_has_ascp_file_list(@job_spec)
|
156
|
-
# set if paths is mandatory in ts
|
157
|
-
@builder.params_definition['paths'][:mandatory] = !@job_spec.has_key?('keepalive') && !ascp_file_list_provided
|
158
|
-
# get paths in transfer spec (after setting if it is mandatory)
|
159
|
-
ts_paths_array = @builder.process_param('paths',:get_value)
|
160
|
-
if ascp_file_list_provided && !ts_paths_array.nil?
|
161
|
-
raise 'file list provided both in transfer spec and ascp file list. Remove one of them.'
|
162
|
-
end
|
163
|
-
# option 1: EX_file_list
|
164
|
-
file_list_file = @builder.process_param('EX_file_list',:get_value)
|
165
|
-
if !file_list_file.nil?
|
166
|
-
option = '--file-list'
|
167
|
-
else
|
168
|
-
# option 2: EX_file_pair_list
|
169
|
-
file_list_file = @builder.process_param('EX_file_pair_list',:get_value)
|
170
|
-
if !file_list_file.nil?
|
171
|
-
option = '--file-pair-list'
|
172
|
-
elsif !ts_paths_array.nil?
|
173
|
-
# option 3: in TS, it is an array
|
174
|
-
if !self.class.file_list_folder.nil?
|
175
|
-
# safer option: generate a file list file if there is storage defined for it
|
176
|
-
# if there is destination in paths, then use filepairlist
|
177
|
-
# TODO: well, we test only the first one, but anyway it shall be consistent
|
178
|
-
if ts_paths_array.first.has_key?('destination')
|
179
|
-
option = '--file-pair-list'
|
180
|
-
lines = ts_paths_array.each_with_object([]){|e,m|m.push(e['source'],e['destination']);}
|
181
|
-
else
|
182
|
-
option = '--file-list'
|
183
|
-
lines = ts_paths_array.map{|i|i['source']}
|
184
|
-
end
|
185
|
-
file_list_file = Aspera::TempFileManager.instance.new_file_path_in_folder(self.class.file_list_folder)
|
186
|
-
File.write(file_list_file, lines.join("\n"))
|
187
|
-
Log.log.debug{"#{option}=\n#{File.read(file_list_file)}".red}
|
188
|
-
else
|
189
|
-
# not safe for special characters ? (maybe not, depends on OS)
|
190
|
-
Log.log.debug('placing source file list on command line (no file list file)')
|
191
|
-
@builder.add_command_line_options(ts_paths_array.map{|i|i['source']})
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
195
|
-
@builder.add_command_line_options(["#{option}=#{file_list_file}"]) unless option.nil?
|
196
|
-
end
|
210
|
+
# get list of files to transfer and build arg for ascp
|
211
|
+
process_file_list
|
197
212
|
# optional args, at the end to override previous ones (to allow override)
|
198
|
-
@builder.add_command_line_options(@builder.process_param('EX_ascp_args'
|
213
|
+
@builder.add_command_line_options(@builder.process_param('EX_ascp_args', :get_value))
|
199
214
|
# process destination folder
|
200
|
-
destination_folder = @builder.process_param('destination_root'
|
215
|
+
destination_folder = @builder.process_param('destination_root', :get_value) || '/'
|
201
216
|
# ascp4 does not support base64 encoding of destination
|
202
217
|
destination_folder = Base64.strict_encode64(destination_folder) unless env_args[:ascp_version].eql?(:ascp4)
|
203
218
|
# destination MUST be last command line argument to ascp
|
204
219
|
@builder.add_command_line_options([destination_folder])
|
205
220
|
|
206
|
-
@builder.add_env_args(env_args[:env],env_args[:args])
|
221
|
+
@builder.add_env_args(env_args[:env], env_args[:args])
|
207
222
|
|
208
223
|
return env_args
|
209
224
|
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# enum : set with list of values for enum types accepted in transfer spec
|
5
5
|
# tragents : supported agents (for doc only)
|
6
6
|
# required : optional, default: false
|
7
|
-
# cltype : ascp: type of parameter
|
7
|
+
# cltype : ascp: type of parameter: :opt_with_arg,:opt_without_arg,:envvar,:defer,:ignore,
|
8
8
|
# clswitch : ascp: switch for ascp command line
|
9
9
|
# clconvert : ascp: transform value: either a Hash with conversion values, or name of class
|
10
10
|
# clvarname : ascp: name of env var
|
@@ -144,8 +144,11 @@ https_fallback_port:
|
|
144
144
|
:cltype: :opt_with_arg
|
145
145
|
:clswitch: "-t"
|
146
146
|
move_after_transfer:
|
147
|
-
:desc: The relative path to which the files will be moved after the transfer at the source side.
|
147
|
+
:desc: The relative path to which the files will be moved after the transfer at the source side. Available as of 3.8.0.
|
148
148
|
:cltype: :opt_with_arg
|
149
|
+
:tragents:
|
150
|
+
- :direct
|
151
|
+
- :node
|
149
152
|
multi_session:
|
150
153
|
:desc: |
|
151
154
|
Use multi-session transfer. max 128.
|
@@ -310,8 +313,8 @@ ssh_port:
|
|
310
313
|
ssh_private_key:
|
311
314
|
:desc: |-
|
312
315
|
Private key used for SSH authentication.
|
313
|
-
Shall look like: -----BEGIN RSA PRIV4TE KEY
|
314
|
-
Note the JSON encoding:
|
316
|
+
Shall look like: -----BEGIN RSA PRIV4TE KEY-----/nMII...
|
317
|
+
Note the JSON encoding: /n for newlines.
|
315
318
|
|
316
319
|
|
317
320
|
:tragents:
|