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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/BUGS.md +29 -3
- data/CHANGELOG.md +300 -185
- data/CONTRIBUTING.md +74 -23
- data/README.md +2346 -1619
- data/bin/ascli +16 -25
- data/bin/asession +15 -15
- data/examples/dascli +2 -2
- data/examples/proxy.pac +1 -1
- data/lib/aspera/aoc.rb +216 -150
- data/lib/aspera/ascmd.rb +25 -18
- data/lib/aspera/assert.rb +45 -0
- data/lib/aspera/cli/basic_auth_plugin.rb +9 -6
- data/lib/aspera/cli/error.rb +17 -0
- data/lib/aspera/cli/extended_value.rb +51 -16
- data/lib/aspera/cli/formatter.rb +276 -174
- data/lib/aspera/cli/hints.rb +81 -0
- data/lib/aspera/cli/main.rb +114 -147
- data/lib/aspera/cli/manager.rb +181 -136
- data/lib/aspera/cli/plugin.rb +82 -64
- data/lib/aspera/cli/plugins/alee.rb +0 -1
- data/lib/aspera/cli/plugins/aoc.rb +327 -331
- data/lib/aspera/cli/plugins/ats.rb +12 -8
- data/lib/aspera/cli/plugins/bss.rb +2 -2
- data/lib/aspera/cli/plugins/config.rb +575 -439
- data/lib/aspera/cli/plugins/console.rb +40 -0
- data/lib/aspera/cli/plugins/cos.rb +4 -5
- data/lib/aspera/cli/plugins/faspex.rb +111 -92
- data/lib/aspera/cli/plugins/faspex5.rb +245 -182
- data/lib/aspera/cli/plugins/node.rb +239 -160
- data/lib/aspera/cli/plugins/orchestrator.rb +56 -19
- data/lib/aspera/cli/plugins/preview.rb +54 -38
- data/lib/aspera/cli/plugins/server.rb +63 -20
- data/lib/aspera/cli/plugins/shares.rb +64 -38
- data/lib/aspera/cli/sync_actions.rb +68 -0
- data/lib/aspera/cli/transfer_agent.rb +64 -67
- data/lib/aspera/cli/transfer_progress.rb +73 -0
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +3 -1
- data/lib/aspera/command_line_builder.rb +27 -22
- data/lib/aspera/cos_node.rb +6 -4
- data/lib/aspera/coverage.rb +22 -0
- data/lib/aspera/data_repository.rb +33 -2
- data/lib/aspera/environment.rb +21 -8
- data/lib/aspera/fasp/agent_alpha.rb +116 -0
- data/lib/aspera/fasp/agent_base.rb +40 -76
- data/lib/aspera/fasp/agent_connect.rb +21 -22
- data/lib/aspera/fasp/agent_direct.rb +169 -179
- data/lib/aspera/fasp/agent_httpgw.rb +200 -195
- data/lib/aspera/fasp/agent_node.rb +43 -35
- data/lib/aspera/fasp/agent_trsdk.rb +124 -41
- data/lib/aspera/fasp/error_info.rb +2 -2
- data/lib/aspera/fasp/faux_file.rb +52 -0
- data/lib/aspera/fasp/installation.rb +89 -191
- data/lib/aspera/fasp/management.rb +249 -0
- data/lib/aspera/fasp/parameters.rb +86 -47
- data/lib/aspera/fasp/parameters.yaml +75 -8
- data/lib/aspera/fasp/products.rb +162 -0
- data/lib/aspera/fasp/resume_policy.rb +7 -5
- data/lib/aspera/fasp/sync.rb +273 -0
- data/lib/aspera/fasp/transfer_spec.rb +10 -8
- data/lib/aspera/fasp/uri.rb +6 -6
- data/lib/aspera/faspex_gw.rb +11 -8
- data/lib/aspera/faspex_postproc.rb +8 -7
- data/lib/aspera/hash_ext.rb +2 -2
- data/lib/aspera/id_generator.rb +3 -1
- data/lib/aspera/json_rpc.rb +51 -0
- data/lib/aspera/keychain/encrypted_hash.rb +46 -11
- data/lib/aspera/keychain/macos_security.rb +15 -13
- data/lib/aspera/line_logger.rb +23 -0
- data/lib/aspera/log.rb +61 -19
- data/lib/aspera/nagios.rb +7 -2
- data/lib/aspera/node.rb +105 -21
- data/lib/aspera/node_simulator.rb +214 -0
- data/lib/aspera/oauth.rb +57 -36
- data/lib/aspera/open_application.rb +4 -4
- data/lib/aspera/persistency_action_once.rb +13 -14
- data/lib/aspera/persistency_folder.rb +5 -4
- data/lib/aspera/preview/file_types.rb +56 -268
- data/lib/aspera/preview/generator.rb +28 -39
- data/lib/aspera/preview/options.rb +2 -0
- data/lib/aspera/preview/terminal.rb +36 -16
- data/lib/aspera/preview/utils.rb +23 -29
- data/lib/aspera/proxy_auto_config.rb +6 -3
- data/lib/aspera/rest.rb +127 -80
- data/lib/aspera/rest_call_error.rb +1 -1
- data/lib/aspera/rest_error_analyzer.rb +16 -14
- data/lib/aspera/rest_errors_aspera.rb +39 -34
- data/lib/aspera/secret_hider.rb +18 -17
- data/lib/aspera/ssh.rb +10 -5
- data/lib/aspera/temp_file_manager.rb +11 -4
- data/lib/aspera/web_auth.rb +10 -7
- data/lib/aspera/web_server_simple.rb +11 -5
- data.tar.gz.sig +0 -0
- metadata +108 -39
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/listener/line_dump.rb +0 -19
- data/lib/aspera/cli/listener/logger.rb +0 -22
- data/lib/aspera/cli/listener/progress.rb +0 -50
- data/lib/aspera/cli/listener/progress_multi.rb +0 -84
- data/lib/aspera/cli/plugins/sync.rb +0 -44
- data/lib/aspera/fasp/listener.rb +0 -13
- 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
|
-
|
|
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)
|
|
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
|
-
|
|
70
|
-
"#{options[:cli][:switch]} #{
|
|
71
|
-
|
|
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
|
-
|
|
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(:
|
|
127
|
-
|
|
128
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
|
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
|
-
@
|
|
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
|
-
|
|
224
|
-
@builder.add_command_line_options(['--dest64'])
|
|
256
|
+
base64_destination = true
|
|
225
257
|
end
|
|
226
|
-
#
|
|
227
|
-
|
|
228
|
-
# optional
|
|
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)
|
|
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
|
-
|
|
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:
|
|
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: :
|
|
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
|
-
- :
|
|
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
|
-
- :
|
|
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
|
|
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
|