aspera-cli 4.14.0 → 4.16.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 (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