aspera-cli 4.10.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.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/BUGS.md +20 -0
  4. data/CHANGELOG.md +509 -0
  5. data/CONTRIBUTING.md +118 -0
  6. data/README.md +621 -378
  7. data/bin/ascli +4 -4
  8. data/bin/asession +11 -11
  9. data/docs/test_env.conf +28 -19
  10. data/examples/aoc.rb +4 -4
  11. data/examples/dascli +11 -9
  12. data/examples/faspex4.rb +8 -8
  13. data/examples/node.rb +11 -11
  14. data/examples/server.rb +9 -9
  15. data/lib/aspera/aoc.rb +273 -266
  16. data/lib/aspera/ascmd.rb +56 -54
  17. data/lib/aspera/ats_api.rb +4 -4
  18. data/lib/aspera/cli/basic_auth_plugin.rb +15 -12
  19. data/lib/aspera/cli/extended_value.rb +5 -5
  20. data/lib/aspera/cli/formater.rb +64 -64
  21. data/lib/aspera/cli/listener/line_dump.rb +1 -1
  22. data/lib/aspera/cli/listener/logger.rb +1 -1
  23. data/lib/aspera/cli/listener/progress.rb +5 -6
  24. data/lib/aspera/cli/listener/progress_multi.rb +14 -19
  25. data/lib/aspera/cli/main.rb +66 -67
  26. data/lib/aspera/cli/manager.rb +110 -110
  27. data/lib/aspera/cli/plugin.rb +54 -37
  28. data/lib/aspera/cli/plugins/alee.rb +4 -4
  29. data/lib/aspera/cli/plugins/aoc.rb +308 -669
  30. data/lib/aspera/cli/plugins/ats.rb +44 -46
  31. data/lib/aspera/cli/plugins/bss.rb +10 -10
  32. data/lib/aspera/cli/plugins/config.rb +447 -344
  33. data/lib/aspera/cli/plugins/console.rb +12 -12
  34. data/lib/aspera/cli/plugins/cos.rb +18 -20
  35. data/lib/aspera/cli/plugins/faspex.rb +110 -112
  36. data/lib/aspera/cli/plugins/faspex5.rb +67 -46
  37. data/lib/aspera/cli/plugins/node.rb +364 -288
  38. data/lib/aspera/cli/plugins/orchestrator.rb +46 -46
  39. data/lib/aspera/cli/plugins/preview.rb +122 -114
  40. data/lib/aspera/cli/plugins/server.rb +137 -83
  41. data/lib/aspera/cli/plugins/shares.rb +30 -29
  42. data/lib/aspera/cli/plugins/sync.rb +13 -33
  43. data/lib/aspera/cli/transfer_agent.rb +57 -57
  44. data/lib/aspera/cli/version.rb +1 -1
  45. data/lib/aspera/colors.rb +3 -3
  46. data/lib/aspera/command_line_builder.rb +27 -27
  47. data/lib/aspera/cos_node.rb +22 -20
  48. data/lib/aspera/data_repository.rb +1 -1
  49. data/lib/aspera/environment.rb +30 -28
  50. data/lib/aspera/fasp/agent_base.rb +15 -15
  51. data/lib/aspera/fasp/agent_connect.rb +23 -21
  52. data/lib/aspera/fasp/agent_direct.rb +65 -67
  53. data/lib/aspera/fasp/agent_httpgw.rb +72 -68
  54. data/lib/aspera/fasp/agent_node.rb +23 -21
  55. data/lib/aspera/fasp/agent_trsdk.rb +20 -20
  56. data/lib/aspera/fasp/error.rb +3 -2
  57. data/lib/aspera/fasp/error_info.rb +11 -8
  58. data/lib/aspera/fasp/installation.rb +78 -78
  59. data/lib/aspera/fasp/listener.rb +1 -1
  60. data/lib/aspera/fasp/parameters.rb +75 -72
  61. data/lib/aspera/fasp/parameters.yaml +2 -2
  62. data/lib/aspera/fasp/resume_policy.rb +8 -8
  63. data/lib/aspera/fasp/transfer_spec.rb +35 -2
  64. data/lib/aspera/fasp/uri.rb +7 -7
  65. data/lib/aspera/faspex_gw.rb +7 -5
  66. data/lib/aspera/hash_ext.rb +3 -3
  67. data/lib/aspera/id_generator.rb +5 -5
  68. data/lib/aspera/keychain/encrypted_hash.rb +23 -28
  69. data/lib/aspera/keychain/macos_security.rb +21 -20
  70. data/lib/aspera/log.rb +7 -7
  71. data/lib/aspera/nagios.rb +19 -18
  72. data/lib/aspera/node.rb +209 -35
  73. data/lib/aspera/oauth.rb +37 -36
  74. data/lib/aspera/open_application.rb +19 -11
  75. data/lib/aspera/persistency_action_once.rb +4 -4
  76. data/lib/aspera/persistency_folder.rb +13 -13
  77. data/lib/aspera/preview/file_types.rb +8 -8
  78. data/lib/aspera/preview/generator.rb +67 -67
  79. data/lib/aspera/preview/utils.rb +27 -27
  80. data/lib/aspera/proxy_auto_config.js +41 -41
  81. data/lib/aspera/proxy_auto_config.rb +16 -16
  82. data/lib/aspera/rest.rb +56 -60
  83. data/lib/aspera/rest_call_error.rb +2 -1
  84. data/lib/aspera/rest_error_analyzer.rb +18 -17
  85. data/lib/aspera/rest_errors_aspera.rb +16 -16
  86. data/lib/aspera/secret_hider.rb +15 -13
  87. data/lib/aspera/ssh.rb +11 -10
  88. data/lib/aspera/sync.rb +158 -44
  89. data/lib/aspera/temp_file_manager.rb +2 -2
  90. data/lib/aspera/uri_reader.rb +4 -4
  91. data/lib/aspera/web_auth.rb +14 -13
  92. data.tar.gz.sig +0 -0
  93. metadata +8 -5
  94. 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,:PRODUCT_CLI_V1,:PRODUCT_DRIVE,:PRODUCT_ENTSRV,:EXT_RUBY_PROTOBUF,:RB_SDK_FOLDER,
47
- :ONE_YEAR_SECONDS,:DEFAULT_ASPERA_CONF,:DUMMY_CERT_INFO
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("ascp_path=#{@path_to_ascp}")
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("Found #{item[:app_root]}")
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,:ascp4
134
+ when :ascp, :ascp4
135
135
  use_ascp_from_product(FIRST_FOUND) if @path_to_ascp.nil?
136
136
  file = @path_to_ascp
137
- # note that there might be a .exe at the end
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,:fallback_key
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("checking connect port file: #{uri_file}")
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',*DataRepository.instance.data(3).unpack('NnnnnN'))
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,11 +210,11 @@ 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
@@ -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
- Environment.restrict_file_access(ascp_path, mode: 0755)
273
- Environment.restrict_file_access(ascp_path.gsub('ascp','ascp4'), mode: 0755)
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("No #{trd_path} in SDK archive") unless File.exist?(trd_path)
277
- Environment.restrict_file_access(trd_path, mode: 0755) if File.exist?(trd_path)
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,:ETC_SUBFOLDER,:VARRUN_SUBFOLDER,:PRODUCT_INFO
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
@@ -3,7 +3,7 @@
3
3
  module Aspera
4
4
  module Fasp
5
5
  # imlement this class to get transfer events
6
- class Listener
6
+ class Listener # rubocop:disable Lint/EmptyClass
7
7
  # define one of the following methods:
8
8
  # event_text(text_data)
9
9
  # event_struct(legacy_names)
@@ -31,29 +31,29 @@ 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
54
  when :opt_without_arg then i[:clswitch]
55
55
  when :opt_with_arg
56
- values=if i.has_key?(:enum)
56
+ values = if i.key?(:enum)
57
57
  ['enum']
58
58
  elsif i[:accepted_types].is_a?(Array)
59
59
  i[:accepted_types]
@@ -62,20 +62,21 @@ module Aspera
62
62
  else
63
63
  raise "error: #{param}"
64
64
  end.map{|n|"{#{n}}"}.join('|')
65
- conv=i.has_key?(:clconvert) ? '(conversion)' : ''
65
+ conv = i.key?(:clconvert) ? '(conversion)' : ''
66
66
  "#{i[:clswitch]} #{conv}#{values}"
67
67
  else ''
68
68
  end
69
- if i.has_key?(:enum)
69
+ if i.key?(:enum)
70
70
  param[:description] += "\nAllowed values: #{i[:enum].join(', ')}"
71
71
  end
72
+ param[:description] = param[:description].gsub('&sol;', '/') if to_text
72
73
  result.push(param)
73
74
  end
74
75
  return result
75
76
  end
76
77
 
77
78
  # special encoding methods used in YAML (key: :clconvert)
78
- def clconv_remove_hyphen(v); v.tr('-',''); end
79
+ def clconv_remove_hyphen(v); v.tr('-', ''); end
79
80
 
80
81
  # special encoding methods used in YAML (key: :clconvert)
81
82
  def clconv_json64(v); Base64.strict_encode64(JSON.generate(v)); end
@@ -85,13 +86,13 @@ module Aspera
85
86
 
86
87
  # file list is provided directly with ascp arguments
87
88
  def ts_has_ascp_file_list(ts)
88
- (ts['EX_ascp_args'].is_a?(Array) && ['--file-list','--file-pair-list'].any?{|i|ts['EX_ascp_args'].include?(i)}) ||
89
- ts.has_key?('EX_file_list') ||
90
- ts.has_key?('EX_file_pair_list')
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')
91
92
  end
92
93
 
93
- def ts_to_env_args(transfer_spec,options)
94
- 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
95
96
  end
96
97
 
97
98
  # temp file list files are created here
@@ -107,11 +108,56 @@ module Aspera
107
108
  end # self
108
109
 
109
110
  # @param options [Hash] key: :wss: bool
110
- def initialize(job_spec,options)
111
+ def initialize(job_spec, options)
111
112
  @job_spec = job_spec
112
113
  @options = options
113
- @builder = Aspera::CommandLineBuilder.new(@job_spec,self.class.description)
114
- Log.log.debug("agent options: #{@options}")
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?
115
161
  end
116
162
 
117
163
  # translate transfer spec to env vars and command line arguments for ascp
@@ -123,22 +169,22 @@ module Aspera
123
169
  ascp_version: :ascp
124
170
  }
125
171
  # some ssh credentials are required to avoid interactive password input
126
- if !@job_spec.has_key?('remote_password') &&
127
- !@job_spec.has_key?('ssh_private_key') &&
128
- !@job_spec.has_key?('EX_ssh_key_paths')
172
+ if !@job_spec.key?('remote_password') &&
173
+ !@job_spec.key?('ssh_private_key') &&
174
+ !@job_spec.key?('EX_ssh_key_paths')
129
175
  raise Fasp::Error, 'required: password or ssh key (value or path)'
130
176
  end
131
177
 
132
178
  # special cases
133
- @job_spec.delete('source_root') if @job_spec.has_key?('source_root') && @job_spec['source_root'].empty?
179
+ @job_spec.delete('source_root') if @job_spec.key?('source_root') && @job_spec['source_root'].empty?
134
180
 
135
181
  # use web socket session initiation ?
136
- if @builder.process_param('wss_enabled',:get_value) && (@options[:wss] || !@job_spec.has_key?('fasp_port'))
182
+ if @builder.process_param('wss_enabled', :get_value) && (@options[:wss] || !@job_spec.key?('fasp_port'))
137
183
  # by default use web socket session if available, unless removed by user
138
184
  @builder.add_command_line_options(['--ws-connect'])
139
185
  # TODO: option to give order ssh,ws (legacy http is implied bu ssh)
140
186
  # quel bordel:
141
- @job_spec['ssh_port'] = @builder.process_param('wss_port',:get_value)
187
+ @job_spec['ssh_port'] = @builder.process_param('wss_port', :get_value)
142
188
  @job_spec.delete('fasp_port')
143
189
  @job_spec.delete('EX_ssh_key_paths')
144
190
  @job_spec.delete('sshfp')
@@ -154,68 +200,25 @@ module Aspera
154
200
  @builder.process_params
155
201
 
156
202
  # symbol must be index of Installation.paths
157
- if @builder.process_param('use_ascp4',:get_value)
203
+ if @builder.process_param('use_ascp4', :get_value)
158
204
  env_args[:ascp_version] = :ascp4
159
205
  else
160
206
  env_args[:ascp_version] = :ascp
161
207
  # destination will be base64 encoded, put before path arguments
162
208
  @builder.add_command_line_options(['--dest64'])
163
209
  end
164
- # process file lists
165
- begin
166
- # is the file list provided through EX_ parameters?
167
- ascp_file_list_provided = self.class.ts_has_ascp_file_list(@job_spec)
168
- # set if paths is mandatory in ts
169
- @builder.params_definition['paths'][:mandatory] = !@job_spec.has_key?('keepalive') && !ascp_file_list_provided
170
- # get paths in transfer spec (after setting if it is mandatory)
171
- ts_paths_array = @builder.process_param('paths',:get_value)
172
- if ascp_file_list_provided && !ts_paths_array.nil?
173
- raise 'file list provided both in transfer spec and ascp file list. Remove one of them.'
174
- end
175
- # option 1: EX_file_list
176
- file_list_file = @builder.process_param('EX_file_list',:get_value)
177
- if !file_list_file.nil?
178
- option = '--file-list'
179
- else
180
- # option 2: EX_file_pair_list
181
- file_list_file = @builder.process_param('EX_file_pair_list',:get_value)
182
- if !file_list_file.nil?
183
- option = '--file-pair-list'
184
- elsif !ts_paths_array.nil?
185
- # option 3: in TS, it is an array
186
- if !self.class.file_list_folder.nil?
187
- # safer option: generate a file list file if there is storage defined for it
188
- # if there is destination in paths, then use filepairlist
189
- # TODO: well, we test only the first one, but anyway it shall be consistent
190
- if ts_paths_array.first.has_key?('destination')
191
- option = '--file-pair-list'
192
- lines = ts_paths_array.each_with_object([]){|e,m|m.push(e['source'],e['destination']);}
193
- else
194
- option = '--file-list'
195
- lines = ts_paths_array.map{|i|i['source']}
196
- end
197
- file_list_file = Aspera::TempFileManager.instance.new_file_path_in_folder(self.class.file_list_folder)
198
- File.write(file_list_file, lines.join("\n"))
199
- Log.log.debug{"#{option}=\n#{File.read(file_list_file)}".red}
200
- else
201
- # not safe for special characters ? (maybe not, depends on OS)
202
- Log.log.debug('placing source file list on command line (no file list file)')
203
- @builder.add_command_line_options(ts_paths_array.map{|i|i['source']})
204
- end
205
- end
206
- end
207
- @builder.add_command_line_options(["#{option}=#{file_list_file}"]) unless option.nil?
208
- end
210
+ # get list of files to transfer and build arg for ascp
211
+ process_file_list
209
212
  # optional args, at the end to override previous ones (to allow override)
210
- @builder.add_command_line_options(@builder.process_param('EX_ascp_args',:get_value))
213
+ @builder.add_command_line_options(@builder.process_param('EX_ascp_args', :get_value))
211
214
  # process destination folder
212
- destination_folder = @builder.process_param('destination_root',:get_value) || '/'
215
+ destination_folder = @builder.process_param('destination_root', :get_value) || '/'
213
216
  # ascp4 does not support base64 encoding of destination
214
217
  destination_folder = Base64.strict_encode64(destination_folder) unless env_args[:ascp_version].eql?(:ascp4)
215
218
  # destination MUST be last command line argument to ascp
216
219
  @builder.add_command_line_options([destination_folder])
217
220
 
218
- @builder.add_env_args(env_args[:env],env_args[:args])
221
+ @builder.add_env_args(env_args[:env], env_args[:args])
219
222
 
220
223
  return env_args
221
224
  end
@@ -313,8 +313,8 @@ ssh_port:
313
313
  ssh_private_key:
314
314
  :desc: |-
315
315
  Private key used for SSH authentication.
316
- Shall look like: -----BEGIN RSA PRIV4TE KEY-----\nMII...
317
- Note the JSON encoding: \n for newlines.
316
+ Shall look like: -----BEGIN RSA PRIV4TE KEY-----&sol;nMII...
317
+ Note the JSON encoding: &sol;n for newlines.
318
318
 
319
319
 
320
320
  :tragents:
@@ -20,13 +20,13 @@ module Aspera
20
20
  @parameters = DEFAULTS.dup
21
21
  if !params.nil?
22
22
  raise "expecting Hash (or nil), but have #{params.class}" unless params.is_a?(Hash)
23
- params.each do |k,v|
24
- raise "unknown resume parameter: #{k}, expect one of #{DEFAULTS.keys.map(&:to_s).join(',')}" unless DEFAULTS.has_key?(k)
23
+ params.each do |k, v|
24
+ raise "unknown resume parameter: #{k}, expect one of #{DEFAULTS.keys.map(&:to_s).join(',')}" unless DEFAULTS.key?(k)
25
25
  raise "#{k} must be Integer" unless v.is_a?(Integer)
26
26
  @parameters[k] = v
27
27
  end
28
28
  end
29
- Log.log.debug("resume params=#{@parameters}")
29
+ Log.log.debug{"resume params=#{@parameters}"}
30
30
  end
31
31
 
32
32
  # calls block a number of times (resumes) until success or limit reached
@@ -36,20 +36,20 @@ module Aspera
36
36
  # maximum of retry
37
37
  remaining_resumes = @parameters[:iter_max]
38
38
  sleep_seconds = @parameters[:sleep_initial]
39
- Log.log.debug("retries=#{remaining_resumes}")
39
+ Log.log.debug{"retries=#{remaining_resumes}"}
40
40
  # try to send the file until ascp is succesful
41
41
  loop do
42
- Log.log.debug('transfer starting');
42
+ Log.log.debug('transfer starting')
43
43
  begin
44
44
  # call provided block
45
45
  yield
46
46
  break
47
47
  rescue Fasp::Error => e
48
- Log.log.warn("An error occurred: #{e.message}");
48
+ Log.log.warn{"An error occurred: #{e.message}"}
49
49
  # failure in ascp
50
50
  if e.retryable?
51
51
  # exit if we exceed the max number of retry
52
- raise Fasp::Error,'Maximum number of retry reached' if remaining_resumes <= 0
52
+ raise Fasp::Error, 'Maximum number of retry reached' if remaining_resumes <= 0
53
53
  else
54
54
  # give one chance only to non retryable errors
55
55
  unless remaining_resumes.eql?(@parameters[:iter_max])
@@ -61,7 +61,7 @@ module Aspera
61
61
 
62
62
  # take this retry in account
63
63
  remaining_resumes -= 1
64
- Log.log.warn("resuming in #{sleep_seconds} seconds (retry left:#{remaining_resumes})");
64
+ Log.log.warn{"resuming in #{sleep_seconds} seconds (retry left:#{remaining_resumes})"}
65
65
 
66
66
  # wait a bit before retrying, maybe network condition will be better
67
67
  sleep(sleep_seconds)