aspera-cli 4.14.0 → 4.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/BUGS.md +29 -3
  4. data/CHANGELOG.md +300 -185
  5. data/CONTRIBUTING.md +74 -23
  6. data/README.md +2346 -1619
  7. data/bin/ascli +16 -25
  8. data/bin/asession +15 -15
  9. data/examples/dascli +2 -2
  10. data/examples/proxy.pac +1 -1
  11. data/lib/aspera/aoc.rb +216 -150
  12. data/lib/aspera/ascmd.rb +25 -18
  13. data/lib/aspera/assert.rb +45 -0
  14. data/lib/aspera/cli/basic_auth_plugin.rb +9 -6
  15. data/lib/aspera/cli/error.rb +17 -0
  16. data/lib/aspera/cli/extended_value.rb +51 -16
  17. data/lib/aspera/cli/formatter.rb +276 -174
  18. data/lib/aspera/cli/hints.rb +81 -0
  19. data/lib/aspera/cli/main.rb +114 -147
  20. data/lib/aspera/cli/manager.rb +181 -136
  21. data/lib/aspera/cli/plugin.rb +82 -64
  22. data/lib/aspera/cli/plugins/alee.rb +0 -1
  23. data/lib/aspera/cli/plugins/aoc.rb +327 -331
  24. data/lib/aspera/cli/plugins/ats.rb +12 -8
  25. data/lib/aspera/cli/plugins/bss.rb +2 -2
  26. data/lib/aspera/cli/plugins/config.rb +575 -439
  27. data/lib/aspera/cli/plugins/console.rb +40 -0
  28. data/lib/aspera/cli/plugins/cos.rb +4 -5
  29. data/lib/aspera/cli/plugins/faspex.rb +111 -92
  30. data/lib/aspera/cli/plugins/faspex5.rb +245 -182
  31. data/lib/aspera/cli/plugins/node.rb +239 -160
  32. data/lib/aspera/cli/plugins/orchestrator.rb +56 -19
  33. data/lib/aspera/cli/plugins/preview.rb +54 -38
  34. data/lib/aspera/cli/plugins/server.rb +63 -20
  35. data/lib/aspera/cli/plugins/shares.rb +64 -38
  36. data/lib/aspera/cli/sync_actions.rb +68 -0
  37. data/lib/aspera/cli/transfer_agent.rb +64 -67
  38. data/lib/aspera/cli/transfer_progress.rb +73 -0
  39. data/lib/aspera/cli/version.rb +1 -1
  40. data/lib/aspera/colors.rb +3 -1
  41. data/lib/aspera/command_line_builder.rb +27 -22
  42. data/lib/aspera/cos_node.rb +6 -4
  43. data/lib/aspera/coverage.rb +22 -0
  44. data/lib/aspera/data_repository.rb +33 -2
  45. data/lib/aspera/environment.rb +21 -8
  46. data/lib/aspera/fasp/agent_alpha.rb +116 -0
  47. data/lib/aspera/fasp/agent_base.rb +40 -76
  48. data/lib/aspera/fasp/agent_connect.rb +21 -22
  49. data/lib/aspera/fasp/agent_direct.rb +169 -179
  50. data/lib/aspera/fasp/agent_httpgw.rb +200 -195
  51. data/lib/aspera/fasp/agent_node.rb +43 -35
  52. data/lib/aspera/fasp/agent_trsdk.rb +124 -41
  53. data/lib/aspera/fasp/error_info.rb +2 -2
  54. data/lib/aspera/fasp/faux_file.rb +52 -0
  55. data/lib/aspera/fasp/installation.rb +89 -191
  56. data/lib/aspera/fasp/management.rb +249 -0
  57. data/lib/aspera/fasp/parameters.rb +86 -47
  58. data/lib/aspera/fasp/parameters.yaml +75 -8
  59. data/lib/aspera/fasp/products.rb +162 -0
  60. data/lib/aspera/fasp/resume_policy.rb +7 -5
  61. data/lib/aspera/fasp/sync.rb +273 -0
  62. data/lib/aspera/fasp/transfer_spec.rb +10 -8
  63. data/lib/aspera/fasp/uri.rb +6 -6
  64. data/lib/aspera/faspex_gw.rb +11 -8
  65. data/lib/aspera/faspex_postproc.rb +8 -7
  66. data/lib/aspera/hash_ext.rb +2 -2
  67. data/lib/aspera/id_generator.rb +3 -1
  68. data/lib/aspera/json_rpc.rb +51 -0
  69. data/lib/aspera/keychain/encrypted_hash.rb +46 -11
  70. data/lib/aspera/keychain/macos_security.rb +15 -13
  71. data/lib/aspera/line_logger.rb +23 -0
  72. data/lib/aspera/log.rb +61 -19
  73. data/lib/aspera/nagios.rb +7 -2
  74. data/lib/aspera/node.rb +105 -21
  75. data/lib/aspera/node_simulator.rb +214 -0
  76. data/lib/aspera/oauth.rb +57 -36
  77. data/lib/aspera/open_application.rb +4 -4
  78. data/lib/aspera/persistency_action_once.rb +13 -14
  79. data/lib/aspera/persistency_folder.rb +5 -4
  80. data/lib/aspera/preview/file_types.rb +56 -268
  81. data/lib/aspera/preview/generator.rb +28 -39
  82. data/lib/aspera/preview/options.rb +2 -0
  83. data/lib/aspera/preview/terminal.rb +36 -16
  84. data/lib/aspera/preview/utils.rb +23 -29
  85. data/lib/aspera/proxy_auto_config.rb +6 -3
  86. data/lib/aspera/rest.rb +127 -80
  87. data/lib/aspera/rest_call_error.rb +1 -1
  88. data/lib/aspera/rest_error_analyzer.rb +16 -14
  89. data/lib/aspera/rest_errors_aspera.rb +39 -34
  90. data/lib/aspera/secret_hider.rb +18 -17
  91. data/lib/aspera/ssh.rb +10 -5
  92. data/lib/aspera/temp_file_manager.rb +11 -4
  93. data/lib/aspera/web_auth.rb +10 -7
  94. data/lib/aspera/web_server_simple.rb +11 -5
  95. data.tar.gz.sig +0 -0
  96. metadata +108 -39
  97. metadata.gz.sig +0 -0
  98. data/lib/aspera/cli/listener/line_dump.rb +0 -19
  99. data/lib/aspera/cli/listener/logger.rb +0 -22
  100. data/lib/aspera/cli/listener/progress.rb +0 -50
  101. data/lib/aspera/cli/listener/progress_multi.rb +0 -84
  102. data/lib/aspera/cli/plugins/sync.rb +0 -44
  103. data/lib/aspera/fasp/listener.rb +0 -13
  104. data/lib/aspera/sync.rb +0 -213
@@ -1,9 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'aspera/log'
4
+ require 'aspera/assert'
4
5
  require 'aspera/command_line_builder'
5
6
  require 'aspera/temp_file_manager'
6
7
  require 'aspera/fasp/error'
8
+ require 'aspera/fasp/installation'
9
+ require 'aspera/cli/formatter'
10
+ require 'aspera/rest'
7
11
  require 'securerandom'
8
12
  require 'base64'
9
13
  require 'json'
@@ -16,19 +20,20 @@ module Aspera
16
20
  # translate transfer specification to ascp parameter list
17
21
  class Parameters
18
22
  # Agents shown in manual for parameters (sub list)
19
- SUPPORTED_AGENTS = %i[direct node connect].freeze
23
+ SUPPORTED_AGENTS = %i[direct node connect trsdk httpgw].freeze
20
24
  # Short names of columns in manual
21
25
  SUPPORTED_AGENTS_SHORT = SUPPORTED_AGENTS.map{|a|a.to_s[0].to_sym}
22
26
  FILE_LIST_OPTIONS = ['--file-list', '--file-pair-list'].freeze
23
- SUPPORTED_OPTIONS = %i[ascp_args wss].freeze
27
+ # options that can be provided to the constructor, and then in @options
28
+ SUPPORTED_OPTIONS = %i[ascp_args wss check_ignore quiet trusted_certs].freeze
24
29
 
25
- private_constant :SUPPORTED_AGENTS, :FILE_LIST_OPTIONS
30
+ private_constant :SUPPORTED_AGENTS, :FILE_LIST_OPTIONS, :SUPPORTED_OPTIONS
26
31
 
27
32
  class << self
28
33
  # Temp folder for file lists, must contain only file lists
29
34
  # because of garbage collection takes any file there
30
35
  # this could be refined, as , for instance, on macos, temp folder is already user specific
31
- @file_list_folder = TempFileManager.instance.new_file_path_global('asession_filelists')
36
+ @file_list_folder = TempFileManager.instance.new_file_path_global('asession_filelists') # cspell:disable-line
32
37
  @param_description_cache = nil
33
38
  # @return normalized description of transfer spec parameters, direct from yaml
34
39
  def description
@@ -48,7 +53,7 @@ module Aspera
48
53
  param = {name: name, type: [options[:accepted_types]].flatten.join(','), description: options[:desc]}
49
54
  # add flags for supported agents in doc
50
55
  SUPPORTED_AGENTS.each do |a|
51
- param[a.to_s[0].to_sym] = options[:agents].nil? || options[:agents].include?(a) ? 'Y' : ''
56
+ param[a.to_s[0].to_sym] = Cli::Formatter.tick(options[:agents].nil? || options[:agents].include?(a))
52
57
  end
53
58
  # only keep lines that are usable in supported agents
54
59
  next if SUPPORTED_AGENTS_SHORT.inject(true){|m, j|m && param[j].empty?}
@@ -66,9 +71,12 @@ module Aspera
66
71
  else
67
72
  raise "error: #{param}"
68
73
  end.map{|n|"{#{n}}"}.join('|')
69
- conv = options[:cli].key?(:convert) ? '(conversion)' : ''
70
- "#{options[:cli][:switch]} #{conv}#{values}"
71
- else ''
74
+ conversion_tag = options[:cli].key?(:convert) ? '(conversion)' : ''
75
+ "#{options[:cli][:switch]} #{conversion_tag}#{values}"
76
+ when :special then Cli::Formatter.special('special')
77
+ when :ignore then Cli::Formatter.special('ignored')
78
+ else
79
+ param[:d].eql?(tick_yes) ? '' : 'n/a'
72
80
  end
73
81
  if options.key?(:enum)
74
82
  param[:description] += "\nAllowed values: #{options[:enum].join(', ')}"
@@ -119,21 +127,26 @@ module Aspera
119
127
 
120
128
  # @param options [Hash] key: :wss: bool, :ascp_args: array of strings
121
129
  def initialize(job_spec, options)
130
+ assert_type(job_spec, Hash)
131
+ assert_type(options, Hash)
122
132
  @job_spec = job_spec
123
133
  # check necessary options
124
- raise 'Internal: missing options' unless (SUPPORTED_OPTIONS - options.keys).empty?
134
+ missing_options = SUPPORTED_OPTIONS - options.keys
135
+ assert(missing_options.empty?){"missing options: #{missing_options.join(', ')}"}
125
136
  @options = SUPPORTED_OPTIONS.each_with_object({}){|o, h| h[o] = options[o]}
126
- Log.dump(:options, @options)
127
- raise 'ascp args must be an Array' unless @options[:ascp_args].is_a?(Array)
128
- raise 'ascp args must be an Array of String' if @options[:ascp_args].any?{|i|!i.is_a?(String)}
137
+ Log.log.debug{Log.dump(:parameters_options, @options)}
138
+ Log.log.debug{Log.dump(:dismiss_options, options.keys - SUPPORTED_OPTIONS)}
139
+ assert_type(@options[:ascp_args], Array){'ascp_args'}
140
+ assert(@options[:ascp_args].all?(String)){'ascp arguments must Strings'}
129
141
  @builder = Aspera::CommandLineBuilder.new(@job_spec, self.class.description)
130
142
  end
131
143
 
144
+ # either place source files on command line, or add file list file
132
145
  def process_file_list
133
146
  # is the file list provided through EX_ parameters?
134
147
  ascp_file_list_provided = self.class.ts_has_ascp_file_list(@job_spec, @options[:ascp_args])
135
148
  # set if paths is mandatory in ts
136
- @builder.params_definition['paths'][:mandatory] = !@job_spec.key?('keepalive') && !ascp_file_list_provided
149
+ @builder.params_definition['paths'][:mandatory] = !@job_spec.key?('keepalive') && !ascp_file_list_provided # cspell:words keepalive
137
150
  # get paths in transfer spec (after setting if it is mandatory)
138
151
  ts_paths_array = @builder.read_param('paths')
139
152
  if ascp_file_list_provided && !ts_paths_array.nil?
@@ -153,20 +166,21 @@ module Aspera
153
166
  Log.log.debug('placing source file list on command line (no file list file)')
154
167
  @builder.add_command_line_options(ts_paths_array.map{|i|i['source']})
155
168
  else
156
- raise "All elements of paths must have a 'source' key" unless ts_paths_array.all?{|i|i.key?('source')}
169
+ assert(ts_paths_array.all?{|i|i.key?('source')}){"All elements of paths must have a 'source' key"}
157
170
  is_pair_list = ts_paths_array.any?{|i|i.key?('destination')}
158
171
  raise "All elements of paths must be consistent with 'destination' key" if is_pair_list && !ts_paths_array.all?{|i|i.key?('destination')}
159
172
  # safer option: generate a file list file if there is storage defined for it
160
173
  # if there is one destination in paths, then use file-pair-list
161
174
  if is_pair_list
162
175
  option = '--file-pair-list'
163
- lines = ts_paths_array.each_with_object([]){|e, m|m.push(e['source'], e['destination'] || e['source']); }
176
+ lines = ts_paths_array.each_with_object([]){|e, m|m.push(e['source'], e['destination'] || e['source']) }
164
177
  else
165
178
  option = '--file-list'
166
179
  lines = ts_paths_array.map{|i|i['source']}
167
180
  end
168
181
  file_list_file = Aspera::TempFileManager.instance.new_file_path_in_folder(self.class.file_list_folder)
169
- File.write(file_list_file, lines.join("\n"))
182
+ Log.log.debug{Log.dump(:file_list, lines)}
183
+ File.write(file_list_file, lines.join("\n"), encoding: 'UTF-8')
170
184
  Log.log.debug{"#{option}=\n#{File.read(file_list_file)}".red}
171
185
  end
172
186
  end
@@ -176,67 +190,92 @@ module Aspera
176
190
  @builder.add_command_line_options(["#{option}=#{file_list_file}"]) unless option.nil?
177
191
  end
178
192
 
179
- # translate transfer spec to env vars and command line arguments for ascp
180
- # NOTE: parameters starting with "EX_" (extended) are not standard
181
- def ascp_args
182
- env_args = {
183
- args: [],
184
- env: {},
185
- ascp_version: :ascp
186
- }
187
- # some ssh credentials are required to avoid interactive password input
188
- if !@job_spec.key?('remote_password') &&
189
- !@job_spec.key?('ssh_private_key') &&
190
- !@job_spec.key?('EX_ssh_key_paths')
191
- raise Fasp::Error, 'required: password or ssh key (value or path)'
192
- end
193
-
194
- # special cases
195
- @job_spec.delete('source_root') if @job_spec.key?('source_root') && @job_spec['source_root'].empty?
196
-
197
- # use web socket session initiation ?
193
+ def remote_certificates
194
+ certificates_to_use = []
195
+ # use web socket secure for session ?
198
196
  if @builder.read_param('wss_enabled') && (@options[:wss] || !@job_spec.key?('fasp_port'))
199
197
  # by default use web socket session if available, unless removed by user
200
198
  @builder.add_command_line_options(['--ws-connect'])
201
- # TODO: option to give order ssh,ws (legacy http is implied bu ssh)
199
+ # TODO: option to give order ssh,ws (legacy http is implied by ssh)
202
200
  # This will need to be cleaned up in aspera core
203
201
  @job_spec['ssh_port'] = @builder.read_param('wss_port')
204
202
  @job_spec.delete('fasp_port')
205
203
  @job_spec.delete('EX_ssh_key_paths')
206
204
  @job_spec.delete('sshfp')
205
+ # ignore cert for wss ?
206
+ if @options[:check_ignore]&.call(@job_spec['remote_host'], @job_spec['wss_port'])
207
+ wss_cert_file = TempFileManager.instance.new_file_path_global('wss_cert')
208
+ wss_url = "https://#{@job_spec['remote_host']}:#{@job_spec['wss_port']}"
209
+ File.write(wss_cert_file, Rest.remote_certificates(wss_url))
210
+ certificates_to_use.push(wss_cert_file)
211
+ end
207
212
  # set location for CA bundle to be the one of Ruby, see env var SSL_CERT_FILE / SSL_CERT_DIR
208
- @job_spec['EX_ssh_key_paths'] = [OpenSSL::X509::DEFAULT_CERT_FILE]
209
- Log.log.debug('CA certs: EX_ssh_key_paths <- DEFAULT_CERT_FILE from openssl')
213
+ certificates_to_use.concat(@options[:trusted_certs]) if @options[:trusted_certs]
210
214
  else
211
215
  # remove unused parameter (avoid warning)
212
216
  @job_spec.delete('wss_port')
217
+ # add SSH bypass keys when authentication is token and no auth is provided
218
+ if @job_spec.key?('token') && !@job_spec.key?('remote_password')
219
+ # @job_spec['remote_password'] = Installation.instance.ssh_cert_uuid # not used: no passphrase
220
+ certificates_to_use.concat(Installation.instance.aspera_token_ssh_key_paths)
221
+ end
222
+ end
223
+ return certificates_to_use
224
+ end
225
+
226
+ # translate transfer spec to env vars and command line arguments for ascp
227
+ # NOTE: parameters starting with "EX_" (extended) are not standard
228
+ def ascp_args
229
+ env_args = {
230
+ args: [],
231
+ env: {},
232
+ ascp_version: :ascp
233
+ }
234
+
235
+ # special cases
236
+ @job_spec.delete('source_root') if @job_spec.key?('source_root') && @job_spec['source_root'].empty?
237
+
238
+ # notify multi-session was already used, anyway it was deleted by agent direct
239
+ assert(!@builder.read_param('multi_session'))
240
+
241
+ # add ssh or wss certificates
242
+ remote_certificates.each do |cert|
243
+ Log.log.trace1{"adding certificate: #{cert}"}
244
+ env_args[:args].unshift('-i', cert)
213
245
  end
214
246
 
215
247
  # process parameters as specified in table
216
248
  @builder.process_params
217
249
 
250
+ base64_destination = false
218
251
  # symbol must be index of Installation.paths
219
252
  if @builder.read_param('use_ascp4')
220
253
  env_args[:ascp_version] = :ascp4
221
254
  else
222
255
  env_args[:ascp_version] = :ascp
223
- # destination will be base64 encoded, put before path arguments
224
- @builder.add_command_line_options(['--dest64'])
256
+ base64_destination = true
225
257
  end
226
- # get list of files to transfer and build arg for ascp
227
- process_file_list
228
- # optional args, at the end to override previous ones (to allow override)
258
+ # destination will be base64 encoded, put this before source path arguments
259
+ @builder.add_command_line_options(['--dest64']) if base64_destination
260
+ # optional arguments, at the end to override previous ones (to allow override)
229
261
  @builder.add_command_line_options(@builder.read_param('EX_ascp_args'))
230
262
  @builder.add_command_line_options(@options[:ascp_args])
263
+ # get list of source files to transfer and build arg for ascp
264
+ process_file_list
231
265
  # process destination folder
232
266
  destination_folder = @builder.read_param('destination_root') || '/'
233
267
  # ascp4 does not support base64 encoding of destination
234
- destination_folder = Base64.strict_encode64(destination_folder) unless env_args[:ascp_version].eql?(:ascp4)
268
+ destination_folder = Base64.strict_encode64(destination_folder) if base64_destination
235
269
  # destination MUST be last command line argument to ascp
236
270
  @builder.add_command_line_options([destination_folder])
237
-
238
- @builder.add_env_args(env_args[:env], env_args[:args])
239
-
271
+ @builder.add_env_args(env_args)
272
+ env_args[:args].unshift('-q') if @options[:quiet]
273
+ # add fallback cert and key as arguments if needed
274
+ if ['1', 1, true, 'force'].include?(@job_spec['http_fallback'])
275
+ env_args[:args].unshift('-Y', Installation.instance.path(:fallback_private_key))
276
+ env_args[:args].unshift('-I', Installation.instance.path(:fallback_certificate))
277
+ end
278
+ Log.log.debug{"ascp args: #{env_args}"}
240
279
  return env_args
241
280
  end
242
281
  end # Parameters
@@ -2,13 +2,13 @@
2
2
  # accepted_types : accepted types for non-enum
3
3
  # default : default value if not specified
4
4
  # enum : set with list of values for enum types accepted in transfer spec
5
- # agents : supported agents (for doc only)
5
+ # agents : supported agents (for doc only), if not specified: all
6
6
  # required : optional, default: false
7
7
  # cli.type : ascp: type of parameter, one of CLI_OPTION_TYPES
8
8
  # cli.switch : ascp: switch for ascp command line
9
9
  # cli.convert : ascp: transform value: either a Hash with conversion values, or name of class
10
10
  # cli.variable : ascp: name of env var
11
- # cspell:words dgram
11
+ # cspell:words dgram dnat dnats faspmgr asperanoded xattrs keepalive datagram
12
12
  ---
13
13
  cipher:
14
14
  :desc: "In transit encryption type."
@@ -79,7 +79,11 @@ destination_root:
79
79
  :cli:
80
80
  :type: :special
81
81
  destination_root_id:
82
- :desc: The file ID of the destination root directory. Required when using Bearer token auth for the destination node.
82
+ :desc: |-
83
+ The file ID of the destination root directory.
84
+ Required when using Bearer token auth for the destination node.
85
+
86
+
83
87
  :accepted_types: :string
84
88
  :agents:
85
89
  - :sdk
@@ -177,7 +181,7 @@ multi_session:
177
181
 
178
182
  :accepted_types: :int
179
183
  :cli:
180
- :type: :ignore
184
+ :type: :special
181
185
  :switch: "-C"
182
186
  multi_session_threshold:
183
187
  :desc: |-
@@ -227,15 +231,37 @@ precalculate_job_size:
227
231
  :cli:
228
232
  :type: :opt_without_arg
229
233
  preserve_access_time:
234
+ :desc: |-
235
+ Preserve the source-file access timestamps at the destination.
236
+ Because source access times are updated by the transfer operation,
237
+ the timestamp that is preserved is the one just before to the transfer.
238
+
239
+
230
240
  :cli:
231
241
  :type: :opt_without_arg
232
242
  preserve_creation_time:
243
+ :desc: |-
244
+ (Windows only) Preserve source-file creation timestamps at the destination.
245
+ Only Windows systems retain information about creation time.
246
+ If the destination is not a Windows computer, this option is ignored.
247
+
248
+
233
249
  :cli:
234
250
  :type: :opt_without_arg
235
251
  preserve_modification_time:
252
+ :desc: |-
253
+ Set the modification time, the last time a file or directory was modified (written), of a transferred file
254
+ to the modification of the source file or directory.
255
+ Preserve source-file modification timestamps at the destination.
256
+
257
+
236
258
  :cli:
237
259
  :type: :opt_without_arg
238
260
  preserve_times:
261
+ :desc: Preserve file timestamps.
262
+ :agents:
263
+ - :sdk
264
+ - :node
239
265
  :cli:
240
266
  :type: :opt_without_arg
241
267
  rate_policy:
@@ -437,6 +463,7 @@ use_ascp4:
437
463
  :cli:
438
464
  :type: :special
439
465
  use_system_ssh:
466
+ :desc: TODO, comment...
440
467
  :accepted_types: :string
441
468
  :agents:
442
469
  - :sdk
@@ -454,22 +481,46 @@ source_root:
454
481
  :switch: "--source-prefix64"
455
482
  :convert: Aspera::Fasp::Parameters.convert_base64
456
483
  min_rate_cap_kbps:
484
+ :desc: |-
485
+ The highest minimum rate that an incoming transfer can request, in kilobits per second.
486
+ Client minimum rate requests that exceed the minimum rate cap are ignored.
487
+ The default value of unlimited applies no cap to the minimum rate. (Default: 0)
488
+
489
+
457
490
  :accepted_types: :int
458
491
  :cli:
459
492
  :type: :ignore
460
493
  lock_rate_policy:
494
+ :desc: If true, lock the rate policy to the default value.
461
495
  :accepted_types: :bool
496
+ :agents:
497
+ - :sdk
498
+ - :connect
462
499
  :cli:
463
500
  :type: :ignore
464
501
  lock_target_rate_kbps:
502
+ :desc: |-
503
+ If true, lock the target transfer rate to the default value set for target_rate_kbps.
504
+ If false, users can adjust the transfer rate up to the value set for target_rate_cap_kbps.
505
+
506
+
465
507
  :accepted_types: :bool
466
508
  :cli:
467
509
  :type: :ignore
468
510
  lock_min_rate_kbps:
511
+ :desc: |-
512
+ If true, lock the minimum transfer rate to the value set for min_rate_kbps.
513
+ If false, users can adjust the transfer rate up to the value set for target_rate_cap_kbps.
514
+
515
+
469
516
  :accepted_types: :bool
517
+ :agents:
518
+ - :sdk
519
+ - :connect
470
520
  :cli:
471
521
  :type: :ignore
472
522
  apply_local_docroot:
523
+ :desc: Apply local docroot to source paths.
473
524
  :agents:
474
525
  - :direct
475
526
  - :sdk
@@ -561,7 +612,7 @@ remove_empty_source_directory:
561
612
  :type: :opt_without_arg
562
613
  EX_at_rest_password:
563
614
  :desc: Content protection password
564
- :deprecation: "Use standard spec parameter: content_protection_password"
615
+ :deprecation: "(4.13) Use standard spec parameter: content_protection_password"
565
616
  :agents:
566
617
  - :direct
567
618
  :cli:
@@ -573,6 +624,7 @@ EX_proxy_password:
573
624
  May be overridden by password in URL provided in parameter: proxy.
574
625
 
575
626
 
627
+ :deprecation: (4.14) Use env var ASPERA_PROXY_PASS
576
628
  :agents:
577
629
  - :direct
578
630
  :cli:
@@ -580,14 +632,17 @@ EX_proxy_password:
580
632
  :variable: ASPERA_PROXY_PASS
581
633
  EX_license_text:
582
634
  :desc: "License file text override.\nBy default ascp looks for license file near executable."
635
+ :deprecation: (4.14) Use env var ASPERA_SCP_LICENSE
583
636
  :agents:
584
637
  - :direct
585
638
  :cli:
586
639
  :type: :envvar
587
640
  :variable: ASPERA_SCP_LICENSE
588
641
  keepalive:
642
+ :desc: The session is running in persistent session mode.
589
643
  :agents:
590
- - :none
644
+ - :sdk
645
+ - :direct
591
646
  :cli:
592
647
  :type: :opt_without_arg
593
648
  dgram_size:
@@ -610,6 +665,7 @@ sshfp:
610
665
  :switch: "--check-sshfp"
611
666
  EX_http_proxy_url:
612
667
  :desc: Specify the proxy server address used by HTTP Fallback
668
+ :deprecation: (4.14) TODO, use proxy option ?
613
669
  :agents:
614
670
  - :direct
615
671
  :cli:
@@ -617,6 +673,7 @@ EX_http_proxy_url:
617
673
  :switch: "-x"
618
674
  EX_ssh_key_paths:
619
675
  :desc: Use public key authentication for SSH and specify the private key file paths
676
+ :deprecation: (4.14) Use option transfer_info.ascp_args
620
677
  :accepted_types: :array
621
678
  :agents:
622
679
  - :direct
@@ -625,6 +682,7 @@ EX_ssh_key_paths:
625
682
  :switch: "-i"
626
683
  EX_http_transfer_jpeg:
627
684
  :desc: HTTP transfers as JPEG file
685
+ :deprecation: (4.14) Use option transfer_info.ascp_args
628
686
  :accepted_types: :int
629
687
  :default: '0'
630
688
  :agents:
@@ -634,6 +692,7 @@ EX_http_transfer_jpeg:
634
692
  :switch: "-j"
635
693
  EX_no_read:
636
694
  :desc: no read source
695
+ :deprecation: (4.14) Use option transfer_info.ascp_args
637
696
  :agents:
638
697
  - :direct
639
698
  :cli:
@@ -641,12 +700,14 @@ EX_no_read:
641
700
  :switch: "--no-read"
642
701
  EX_no_write:
643
702
  :desc: no write on destination
703
+ :deprecation: (4.14) Use option transfer_info.ascp_args
644
704
  :agents:
645
705
  - :direct
646
706
  :cli:
647
707
  :type: :opt_without_arg
648
708
  :switch: "--no-write"
649
709
  target_rate_percentage:
710
+ :desc: "TODO: remove ?"
650
711
  :cli:
651
712
  :type: :ignore
652
713
  rate_policy_allowed:
@@ -661,15 +722,18 @@ rate_policy_allowed:
661
722
  :cli:
662
723
  :type: :ignore
663
724
  fasp_url:
725
+ :desc: Only used in Faspex.
664
726
  :agents:
665
727
  - :unknown
666
728
  :cli:
667
729
  :type: :ignore
668
730
  lock_min_rate:
731
+ :desc: "TODO: remove ?"
669
732
  :accepted_types: :bool
670
733
  :cli:
671
734
  :type: :ignore
672
735
  lock_target_rate:
736
+ :desc: "TODO: remove ?"
673
737
  :accepted_types: :bool
674
738
  :cli:
675
739
  :type: :ignore
@@ -684,13 +748,15 @@ cipher_allowed:
684
748
  :cli:
685
749
  :type: :ignore
686
750
  obfuscate_file_names:
751
+ :desc: HTTP Gateway obfuscates file names when set to true.
687
752
  :accepted_types: :bool
688
753
  :agents:
689
- - :unknown
754
+ - :httpgw
690
755
  :cli:
691
756
  :type: :ignore
692
757
  EX_file_list:
693
758
  :desc: source file list
759
+ :deprecation: (4.14) Use command line file list, or option transfer_info.ascp_args
694
760
  :agents:
695
761
  - :direct
696
762
  :cli:
@@ -698,6 +764,7 @@ EX_file_list:
698
764
  :switch: "--file-list"
699
765
  EX_file_pair_list:
700
766
  :desc: source file pair list
767
+ :deprecation: (4.14) Use command line file pair list, or option transfer_info.ascp_args
701
768
  :agents:
702
769
  - :direct
703
770
  :cli:
@@ -705,7 +772,7 @@ EX_file_pair_list:
705
772
  :switch: "--file-pair-list"
706
773
  EX_ascp_args:
707
774
  :desc: Add native command line arguments to ascp
708
- :deprecation: Use parameter ascp_args in option transfer_info
775
+ :deprecation: (4.13) Use option transfer_info.ascp_args
709
776
  :accepted_types: :array
710
777
  :agents:
711
778
  - :direct
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ # cspell:ignore LOCALAPPDATA
4
+ require 'aspera/environment'
5
+
6
+ module Aspera
7
+ module Fasp
8
+ # find Aspera standard products installation in standard paths
9
+ class Products
10
+ # known product names
11
+ CONNECT = 'IBM Aspera Connect'
12
+ ASPERA = 'IBM Aspera (Client)'
13
+ CLI_V1 = 'Aspera CLI (deprecated)'
14
+ DRIVE = 'Aspera Drive (deprecated)'
15
+ HSTS = 'IBM Aspera High-Speed Transfer Server'
16
+ # product information manifest: XML (part of aspera product)
17
+ INFO_META_FILE = 'product-info.mf'
18
+ BIN_SUBFOLDER = 'bin'
19
+ ETC_SUBFOLDER = 'etc'
20
+ VAR_RUN_SUBFOLDER = File.join('var', 'run')
21
+
22
+ @@found_products = nil # rubocop:disable Style/ClassVars
23
+ class << self
24
+ # @return product folders depending on OS fields
25
+ # :expected M app name is taken from the manifest if present, else defaults to this value
26
+ # :app_root M main folder for the application
27
+ # :log_root O location of log files (Linux uses syslog)
28
+ # :run_root O only for Connect Client, location of http port file
29
+ # :sub_bin O subfolder with executables, default : bin
30
+ def product_locations_on_current_os
31
+ result =
32
+ case Aspera::Environment.os
33
+ when Aspera::Environment::OS_WINDOWS then [{
34
+ expected: CONNECT,
35
+ app_root: File.join(ENV.fetch('LOCALAPPDATA', nil), 'Programs', 'Aspera', 'Aspera Connect'),
36
+ log_root: File.join(ENV.fetch('LOCALAPPDATA', nil), 'Aspera', 'Aspera Connect', 'var', 'log'),
37
+ run_root: File.join(ENV.fetch('LOCALAPPDATA', nil), 'Aspera', 'Aspera Connect')
38
+ }, {
39
+ expected: CLI_V1,
40
+ app_root: File.join('C:', 'Program Files', 'Aspera', 'cli'),
41
+ log_root: File.join('C:', 'Program Files', 'Aspera', 'cli', 'var', 'log')
42
+ }, {
43
+ expected: HSTS,
44
+ app_root: File.join('C:', 'Program Files', 'Aspera', 'Enterprise Server'),
45
+ log_root: File.join('C:', 'Program Files', 'Aspera', 'Enterprise Server', 'var', 'log')
46
+ }]
47
+ when Aspera::Environment::OS_X then [{
48
+ expected: CONNECT,
49
+ app_root: File.join(Dir.home, 'Applications', 'Aspera Connect.app'),
50
+ log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera_Connect'),
51
+ run_root: File.join(Dir.home, 'Library', 'Application Support', 'Aspera', 'Aspera Connect'),
52
+ sub_bin: File.join('Contents', 'Resources')
53
+ }, {
54
+ expected: CONNECT,
55
+ app_root: File.join('', 'Applications', 'Aspera Connect.app'),
56
+ log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera_Connect'),
57
+ run_root: File.join(Dir.home, 'Library', 'Application Support', 'Aspera', 'Aspera Connect'),
58
+ sub_bin: File.join('Contents', 'Resources')
59
+ }, {
60
+ expected: CLI_V1,
61
+ app_root: File.join(Dir.home, 'Applications', 'Aspera CLI'),
62
+ log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera')
63
+ }, {
64
+ expected: HSTS,
65
+ app_root: File.join('', 'Library', 'Aspera'),
66
+ log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera')
67
+ }, {
68
+ expected: DRIVE,
69
+ app_root: File.join('', 'Applications', 'Aspera Drive.app'),
70
+ log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera_Drive'),
71
+ sub_bin: File.join('Contents', 'Resources')
72
+ }, {
73
+ expected: ASPERA,
74
+ app_root: File.join('', 'Applications', 'IBM Aspera.app'),
75
+ log_root: File.join(Dir.home, 'Library', 'Logs', 'IBM Aspera'),
76
+ sub_bin: File.join('Contents', 'Resources', 'sdk', 'aspera', 'bin')
77
+ }]
78
+ else [{ # other: Linux and Unix family
79
+ expected: CONNECT,
80
+ app_root: File.join(Dir.home, '.aspera', 'connect'),
81
+ run_root: File.join(Dir.home, '.aspera', 'connect')
82
+ }, {
83
+ expected: CLI_V1,
84
+ app_root: File.join(Dir.home, '.aspera', 'cli')
85
+ }, {
86
+ expected: HSTS,
87
+ app_root: File.join('', 'opt', 'aspera')
88
+ }]
89
+ end
90
+ result # .each {|item| item.deep_do {|h, _k, _v, _m|h.freeze}}.freeze
91
+ end
92
+
93
+ # @return the list of installed products in format of product_locations_on_current_os
94
+ def installed_products
95
+ if @@found_products.nil?
96
+ scan_locations = product_locations_on_current_os.clone
97
+ # add SDK as first search path
98
+ scan_locations.unshift({
99
+ expected: 'SDK',
100
+ app_root: Installation.instance.sdk_folder,
101
+ sub_bin: ''
102
+ })
103
+ # search installed products: with ascp
104
+ @@found_products = scan_locations.select! do |item| # rubocop:disable Style/ClassVars
105
+ # skip if not main folder
106
+ next false unless Dir.exist?(item[:app_root])
107
+ Log.log.debug{"Found #{item[:app_root]}"}
108
+ sub_bin = item[:sub_bin] || BIN_SUBFOLDER
109
+ item[:ascp_path] = File.join(item[:app_root], sub_bin, ascp_filename)
110
+ # skip if no ascp
111
+ next false unless File.exist?(item[:ascp_path])
112
+ # read info from product info file if present
113
+ product_info_file = "#{item[:app_root]}/#{INFO_META_FILE}"
114
+ if File.exist?(product_info_file)
115
+ res_s = XmlSimple.xml_in(File.read(product_info_file), {'ForceArray' => false})
116
+ item[:name] = res_s['name']
117
+ item[:version] = res_s['version']
118
+ else
119
+ item[:name] = item[:expected]
120
+ end
121
+ true # select this version
122
+ end
123
+ end
124
+ return @@found_products
125
+ end
126
+
127
+ # filename for ascp with optional extension (Windows)
128
+ def ascp_filename
129
+ return 'ascp' + Environment.exe_extension
130
+ end
131
+
132
+ # @return folder paths for specified applications
133
+ # @param name Connect or CLI
134
+ def folders(name)
135
+ found = Products.installed_products.select{|i|i[:expected].eql?(name) || i[:name].eql?(name)}
136
+ raise "Product: #{name} not found, please install." if found.empty?
137
+ return found.first
138
+ end
139
+
140
+ # @return the file path of local connect where API's URI can be read
141
+ def connect_uri
142
+ connect = folders(CONNECT)
143
+ folder = File.join(connect[:run_root], VAR_RUN_SUBFOLDER)
144
+ ['', 's'].each do |ext|
145
+ uri_file = File.join(folder, "http#{ext}.uri")
146
+ Log.log.debug{"checking connect port file: #{uri_file}"}
147
+ if File.exist?(uri_file)
148
+ return File.open(uri_file, &:gets).strip
149
+ end
150
+ end
151
+ raise "no connect uri file found in #{folder}"
152
+ end
153
+
154
+ # @ return path to configuration file of aspera CLI
155
+ # def cli_conf_file
156
+ # connect = folders(PRODUCT_CLI_V1)
157
+ # return File.join(connect[:app_root], BIN_SUBFOLDER, '.aspera_cli_conf')
158
+ # end
159
+ end
160
+ end
161
+ end
162
+ end