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.
- 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
|