aspera-cli 4.22.0 → 4.24.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/CHANGELOG.md +405 -364
- data/CONTRIBUTING.md +86 -29
- data/README.md +1856 -961
- data/bin/ascli +2 -1
- data/bin/asession +4 -4
- data/lib/aspera/agent/base.rb +4 -0
- data/lib/aspera/agent/connect.rb +20 -18
- data/lib/aspera/agent/desktop.rb +14 -11
- data/lib/aspera/agent/direct.rb +39 -31
- data/lib/aspera/agent/httpgw.rb +2 -2
- data/lib/aspera/agent/node.rb +9 -11
- data/lib/aspera/agent/transferd.rb +18 -11
- data/lib/aspera/api/aoc.rb +53 -43
- data/lib/aspera/api/cos_node.rb +7 -5
- data/lib/aspera/api/httpgw.rb +23 -22
- data/lib/aspera/api/node.rb +104 -22
- data/lib/aspera/ascmd.rb +35 -21
- data/lib/aspera/ascp/installation.rb +43 -43
- data/lib/aspera/ascp/management.rb +5 -4
- data/lib/aspera/assert.rb +55 -24
- data/lib/aspera/cli/basic_auth_plugin.rb +8 -7
- data/lib/aspera/cli/error.rb +1 -1
- data/lib/aspera/cli/extended_value.rb +28 -29
- data/lib/aspera/cli/formatter.rb +191 -168
- data/lib/aspera/cli/hints.rb +38 -4
- data/lib/aspera/cli/main.rb +139 -108
- data/lib/aspera/cli/manager.rb +51 -31
- data/lib/aspera/cli/plugin.rb +149 -78
- data/lib/aspera/cli/plugin_factory.rb +2 -2
- data/lib/aspera/cli/plugins/aoc.rb +217 -88
- data/lib/aspera/cli/plugins/ats.rb +15 -13
- data/lib/aspera/cli/plugins/config.rb +105 -227
- data/lib/aspera/cli/plugins/console.rb +49 -18
- data/lib/aspera/cli/plugins/cos.rb +4 -4
- data/lib/aspera/cli/plugins/faspex.rb +45 -51
- data/lib/aspera/cli/plugins/faspex5.rb +162 -163
- data/lib/aspera/cli/plugins/faspio.rb +6 -5
- data/lib/aspera/cli/plugins/httpgw.rb +2 -2
- data/lib/aspera/cli/plugins/node.rb +233 -247
- data/lib/aspera/cli/plugins/orchestrator.rb +10 -14
- data/lib/aspera/cli/plugins/preview.rb +26 -29
- data/lib/aspera/cli/plugins/server.rb +29 -28
- data/lib/aspera/cli/plugins/shares.rb +40 -28
- data/lib/aspera/cli/sync_actions.rb +101 -80
- data/lib/aspera/cli/transfer_agent.rb +55 -58
- data/lib/aspera/cli/transfer_progress.rb +29 -20
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +160 -0
- data/lib/aspera/colors.rb +13 -8
- data/lib/aspera/command_line_builder.rb +28 -22
- data/lib/aspera/command_line_converter.rb +31 -0
- data/lib/aspera/data_repository.rb +1 -0
- data/lib/aspera/environment.rb +144 -100
- data/lib/aspera/faspex_gw.rb +1 -1
- data/lib/aspera/faspex_postproc.rb +3 -2
- data/lib/aspera/hash_ext.rb +1 -1
- data/lib/aspera/id_generator.rb +10 -10
- data/lib/aspera/keychain/base.rb +18 -0
- data/lib/aspera/keychain/encrypted_hash.rb +6 -12
- data/lib/aspera/keychain/factory.rb +9 -3
- data/lib/aspera/keychain/hashicorp_vault.rb +9 -6
- data/lib/aspera/keychain/macos_security.rb +13 -13
- data/lib/aspera/log.rb +70 -20
- data/lib/aspera/nagios.rb +5 -6
- data/lib/aspera/node_simulator.rb +12 -7
- data/lib/aspera/oauth/base.rb +6 -2
- data/lib/aspera/oauth/factory.rb +25 -18
- data/lib/aspera/oauth/jwt.rb +13 -1
- data/lib/aspera/oauth/url_json.rb +3 -3
- data/lib/aspera/oauth/web.rb +5 -3
- data/lib/aspera/persistency_folder.rb +2 -2
- data/lib/aspera/preview/file_types.rb +43 -35
- data/lib/aspera/preview/generator.rb +26 -13
- data/lib/aspera/preview/terminal.rb +10 -7
- data/lib/aspera/preview/utils.rb +11 -9
- data/lib/aspera/products/connect.rb +2 -1
- data/lib/aspera/products/desktop.rb +1 -1
- data/lib/aspera/products/other.rb +2 -2
- data/lib/aspera/products/transferd.rb +8 -6
- data/lib/aspera/proxy_auto_config.rb +1 -1
- data/lib/aspera/rest.rb +46 -28
- data/lib/aspera/rest_call_error.rb +1 -1
- data/lib/aspera/rest_error_analyzer.rb +1 -0
- data/lib/aspera/resumer.rb +1 -1
- data/lib/aspera/secret_hider.rb +46 -40
- data/lib/aspera/ssh.rb +14 -4
- data/lib/aspera/sync/args.schema.yaml +102 -0
- data/lib/aspera/sync/conf.schema.yaml +701 -0
- data/lib/aspera/sync/database.rb +83 -0
- data/lib/aspera/{transfer/sync.rb → sync/operations.rb} +145 -68
- data/lib/aspera/temp_file_manager.rb +4 -2
- data/lib/aspera/timer_limiter.rb +7 -5
- data/lib/aspera/transfer/error.rb +1 -1
- data/lib/aspera/transfer/error_info.rb +1 -2
- data/lib/aspera/transfer/faux_file.rb +11 -10
- data/lib/aspera/transfer/parameters.rb +6 -5
- data/lib/aspera/transfer/spec.rb +15 -1
- data/lib/aspera/transfer/spec.schema.yaml +316 -293
- data/lib/aspera/transfer/spec_doc.rb +34 -16
- data/lib/aspera/transfer/uri.rb +5 -5
- data/lib/aspera/uri_reader.rb +14 -10
- data/lib/aspera/web_auth.rb +2 -2
- data/lib/aspera/web_server_simple.rb +2 -2
- data.tar.gz.sig +0 -0
- metadata +15 -15
- metadata.gz.sig +0 -0
- data/examples/dascli +0 -30
- data/examples/get_proto_file.rb +0 -8
- data/examples/proxy.pac +0 -60
- data/lib/aspera/transfer/convert.rb +0 -29
- data/lib/aspera/transfer/sync_instance.schema.yaml +0 -13
- data/lib/aspera/transfer/sync_session.schema.yaml +0 -79
@@ -8,6 +8,7 @@ require 'aspera/cli/version'
|
|
8
8
|
require 'aspera/cli/formatter'
|
9
9
|
require 'aspera/cli/info'
|
10
10
|
require 'aspera/cli/transfer_progress'
|
11
|
+
require 'aspera/cli/wizard'
|
11
12
|
require 'aspera/ascp/installation'
|
12
13
|
require 'aspera/products/transferd'
|
13
14
|
require 'aspera/transfer/error_info'
|
@@ -23,6 +24,7 @@ require 'aspera/persistency_folder'
|
|
23
24
|
require 'aspera/data_repository'
|
24
25
|
require 'aspera/line_logger'
|
25
26
|
require 'aspera/rest'
|
27
|
+
require 'aspera/oauth/jwt'
|
26
28
|
require 'aspera/log'
|
27
29
|
require 'aspera/assert'
|
28
30
|
require 'aspera/oauth'
|
@@ -68,10 +70,7 @@ module Aspera
|
|
68
70
|
EXTEND_VAULT = :vault
|
69
71
|
PRESET_DIG_SEPARATOR = '.'
|
70
72
|
DEFAULT_CHECK_NEW_VERSION_DAYS = 7
|
71
|
-
|
72
|
-
DEFAULT_PRIV_KEY_LENGTH = 4096
|
73
|
-
COFFEE_IMAGE = 'https://enjoyjava.com/wp-content/uploads/2018/01/How-to-make-strong-coffee.jpg'
|
74
|
-
WIZARD_RESULT_KEYS = %i[preset_value test_args].freeze
|
73
|
+
COFFEE_IMAGE_URL = 'https://enjoyjava.com/wp-content/uploads/2018/01/How-to-make-strong-coffee.jpg'
|
75
74
|
GEM_CHECK_DATE_FMT = '%Y/%m/%d'
|
76
75
|
# for testing only
|
77
76
|
SELF_SIGNED_CERT = OpenSSL::SSL.const_get(:enon_yfirev.to_s.upcase.reverse) # cspell: disable-line
|
@@ -90,28 +89,15 @@ module Aspera
|
|
90
89
|
:EXTEND_PRESET,
|
91
90
|
:EXTEND_VAULT,
|
92
91
|
:DEFAULT_CHECK_NEW_VERSION_DAYS,
|
93
|
-
:DEFAULT_PRIV_KEY_FILENAME,
|
94
92
|
:SERVER_COMMAND,
|
95
93
|
:PRESET_DIG_SEPARATOR,
|
96
|
-
:
|
97
|
-
:WIZARD_RESULT_KEYS,
|
94
|
+
:COFFEE_IMAGE_URL,
|
98
95
|
:SELF_SIGNED_CERT,
|
99
96
|
:PERSISTENCY_FOLDER,
|
100
|
-
:DEFAULT_PRIV_KEY_LENGTH,
|
101
97
|
:CONF_OVERVIEW_KEYS,
|
102
98
|
:SMTP_CONF_PARAMS
|
103
99
|
|
104
100
|
class << self
|
105
|
-
def generate_rsa_private_key(path:, length: DEFAULT_PRIV_KEY_LENGTH)
|
106
|
-
require 'openssl'
|
107
|
-
priv_key = OpenSSL::PKey::RSA.new(length)
|
108
|
-
File.write(path, priv_key.to_s)
|
109
|
-
File.write("#{path}.pub", priv_key.public_key.to_s)
|
110
|
-
Environment.restrict_file_access(path)
|
111
|
-
Environment.restrict_file_access("#{path}.pub")
|
112
|
-
nil
|
113
|
-
end
|
114
|
-
|
115
101
|
# folder containing plugins in the gem's main folder
|
116
102
|
def gem_plugins_folder
|
117
103
|
File.dirname(File.expand_path(__FILE__))
|
@@ -132,7 +118,7 @@ module Aspera
|
|
132
118
|
# return product family folder (~/.aspera)
|
133
119
|
def module_family_folder
|
134
120
|
user_home_folder = Dir.home
|
135
|
-
Aspera.assert(Dir.exist?(user_home_folder),
|
121
|
+
Aspera.assert(Dir.exist?(user_home_folder), type: Cli::Error){"Home folder does not exist: #{user_home_folder}. Check your user environment."}
|
136
122
|
return File.join(user_home_folder, ASPERA_HOME_FOLDER_NAME)
|
137
123
|
end
|
138
124
|
|
@@ -171,11 +157,12 @@ module Aspera
|
|
171
157
|
:home, 'Home folder for tool',
|
172
158
|
handler: {o: self, m: :main_folder},
|
173
159
|
types: String,
|
174
|
-
default: self.class.default_app_main_folder(app_name: Info::CMD_NAME)
|
160
|
+
default: self.class.default_app_main_folder(app_name: Info::CMD_NAME)
|
161
|
+
)
|
175
162
|
options.parse_options!
|
176
163
|
Log.log.debug{"#{Info::CMD_NAME} folder: #{@main_folder}"}
|
177
164
|
# data persistency manager, created by config plugin, set for global object
|
178
|
-
|
165
|
+
context.persistency = PersistencyFolder.new(File.join(@main_folder, PERSISTENCY_FOLDER))
|
179
166
|
# set folders for plugin lookup
|
180
167
|
PluginFactory.instance.add_lookup_folder(self.class.gem_plugins_folder)
|
181
168
|
PluginFactory.instance.add_lookup_folder(File.join(@main_folder, ASPERA_PLUGINS_FOLDERNAME))
|
@@ -183,7 +170,8 @@ module Aspera
|
|
183
170
|
options.declare(
|
184
171
|
:config_file, 'Path to YAML file with preset configuration',
|
185
172
|
handler: {o: self, m: :option_config_file},
|
186
|
-
default: File.join(@main_folder, DEFAULT_CONFIG_FILENAME)
|
173
|
+
default: File.join(@main_folder, DEFAULT_CONFIG_FILENAME)
|
174
|
+
)
|
187
175
|
options.parse_options!
|
188
176
|
# read config file (set @config_presets)
|
189
177
|
read_config_file
|
@@ -204,29 +192,26 @@ module Aspera
|
|
204
192
|
options.declare(:preset, 'Load the named option preset from current config file', short: 'P', handler: {o: self, m: :option_preset})
|
205
193
|
options.declare(:version_check_days, 'Period in days to check new version (zero to disable)', coerce: Integer, default: DEFAULT_CHECK_NEW_VERSION_DAYS)
|
206
194
|
options.declare(:plugin_folder, 'Folder where to find additional plugins', handler: {o: self, m: :option_plugin_folder})
|
207
|
-
# wizard options
|
208
|
-
|
209
|
-
options.declare(:default, 'Wizard: set as default configuration for specified plugin (also: update)', values: :bool, default: true)
|
210
|
-
options.declare(:test_mode, 'Wizard: skip private key check step', values: :bool, default: false)
|
211
|
-
options.declare(:key_path, 'Wizard: path to private key for JWT')
|
195
|
+
# declare wizard options
|
196
|
+
@wizard = Wizard.new(self, @main_folder)
|
212
197
|
# Transfer SDK options
|
213
|
-
options.declare(:ascp_path, 'Path to ascp', handler: {o: Ascp::Installation.instance, m: :ascp_path})
|
214
|
-
options.declare(:use_product, 'Use ascp from specified product', handler: {o: self, m: :option_use_product})
|
215
|
-
options.declare(:sdk_url, 'URL to get Aspera Transfer
|
216
|
-
options.declare(:locations_url, 'URL to get locations of Aspera Transfer Daemon', handler: {o: Ascp::Installation.instance, m: :transferd_urls})
|
217
|
-
options.declare(:sdk_folder, 'SDK folder path', handler: {o: Products::Transferd, m: :sdk_directory})
|
198
|
+
options.declare(:ascp_path, 'Ascp: Path to ascp', handler: {o: Ascp::Installation.instance, m: :ascp_path})
|
199
|
+
options.declare(:use_product, 'Ascp: Use ascp from specified product', handler: {o: self, m: :option_use_product})
|
200
|
+
options.declare(:sdk_url, 'Ascp: URL to get Aspera Transfer Executables', default: SpecialValues::DEF)
|
201
|
+
options.declare(:locations_url, 'Ascp: URL to get locations of Aspera Transfer Daemon', handler: {o: Ascp::Installation.instance, m: :transferd_urls})
|
202
|
+
options.declare(:sdk_folder, 'Ascp: SDK folder path', handler: {o: Products::Transferd, m: :sdk_directory})
|
218
203
|
options.declare(:progress_bar, 'Display progress bar', values: :bool, default: Environment.terminal?)
|
219
204
|
# email options
|
220
|
-
options.declare(:smtp, 'SMTP configuration', types: Hash)
|
221
|
-
options.declare(:notify_to, 'Email
|
222
|
-
options.declare(:notify_template, 'Email ERB template for notification of transfers')
|
205
|
+
options.declare(:smtp, 'Email: SMTP configuration', types: Hash)
|
206
|
+
options.declare(:notify_to, 'Email: Recipient for notification of transfers')
|
207
|
+
options.declare(:notify_template, 'Email: ERB template for notification of transfers')
|
223
208
|
# HTTP options
|
224
|
-
options.declare(:insecure, 'Do not validate any
|
225
|
-
options.declare(:ignore_certificate, 'Do not validate
|
226
|
-
options.declare(:
|
227
|
-
options.declare(:cert_stores, 'List of folder with trusted certificates', types: [Array, String], handler: {o: self, m: :trusted_cert_locations})
|
228
|
-
options.declare(:http_options, 'Options for HTTP/S socket', types: Hash, handler: {o: self, m: :option_http_options}, default: {})
|
229
|
-
options.declare(:http_proxy, 'URL for
|
209
|
+
options.declare(:insecure, 'HTTP/S: Do not validate any certificate', values: :bool, handler: {o: self, m: :option_insecure}, default: :no)
|
210
|
+
options.declare(:ignore_certificate, 'HTTP/S: Do not validate certificate for these URLs', types: Array, handler: {o: self, m: :option_ignore_cert_host_port})
|
211
|
+
options.declare(:warn_insecure, 'HTTP/S: Issue a warning if certificate is ignored', values: :bool, handler: {o: self, m: :option_warn_insecure_cert}, default: :yes)
|
212
|
+
options.declare(:cert_stores, 'HTTP/S: List of folder with trusted certificates', types: [Array, String], handler: {o: self, m: :trusted_cert_locations})
|
213
|
+
options.declare(:http_options, 'HTTP/S: Options for HTTP/S socket', types: Hash, handler: {o: self, m: :option_http_options}, default: {})
|
214
|
+
options.declare(:http_proxy, 'HTTP/S: URL for proxy with optional credentials', types: String, handler: {o: self, m: :option_http_proxy})
|
230
215
|
options.declare(:cache_tokens, 'Save and reuse OAuth tokens', values: :bool, handler: {o: self, m: :option_cache_tokens})
|
231
216
|
options.declare(:fpac, 'Proxy auto configuration script')
|
232
217
|
options.declare(:proxy_credentials, 'HTTP proxy credentials for fpac: user, password', types: Array)
|
@@ -256,7 +241,7 @@ module Aspera
|
|
256
241
|
@pac_exec = ProxyAutoConfig.new(pac_script).register_uri_generic
|
257
242
|
proxy_user_pass = options.get_option(:proxy_credentials)
|
258
243
|
if !proxy_user_pass.nil?
|
259
|
-
Aspera.assert(proxy_user_pass.length.eql?(2),
|
244
|
+
Aspera.assert(proxy_user_pass.length.eql?(2), type: Cli::BadArgument){"proxy_credentials shall have two elements (#{proxy_user_pass.length})"}
|
260
245
|
@pac_exec.proxy_user = proxy_user_pass[0]
|
261
246
|
@pac_exec.proxy_pass = proxy_user_pass[1]
|
262
247
|
end
|
@@ -362,7 +347,8 @@ module Aspera
|
|
362
347
|
if !@ssl_warned_urls.include?(base_url)
|
363
348
|
formatter.display_message(
|
364
349
|
:error,
|
365
|
-
"#{Formatter::WARNING_FLASH} Ignoring certificate for: #{base_url}. Do not deactivate certificate verification in production."
|
350
|
+
"#{Formatter::WARNING_FLASH} Ignoring certificate for: #{base_url}. Do not deactivate certificate verification in production."
|
351
|
+
)
|
366
352
|
@ssl_warned_urls.push(base_url)
|
367
353
|
end
|
368
354
|
end
|
@@ -378,13 +364,39 @@ module Aspera
|
|
378
364
|
# Rest.io_http_session(http_session).debug_output = Log.log
|
379
365
|
http_session.verify_mode = SELF_SIGNED_CERT if http_session.use_ssl? && ignore_cert?(http_session.address, http_session.port)
|
380
366
|
http_session.cert_store = @certificate_store if @certificate_store
|
381
|
-
Log.log.debug{"
|
367
|
+
Log.log.debug{"Using cert store #{http_session.cert_store} (#{@certificate_store})"} unless http_session.cert_store.nil?
|
382
368
|
@option_http_options.each do |k, v|
|
383
369
|
method = "#{k}=".to_sym
|
384
370
|
# check if accessor is a method of Net::HTTP
|
385
371
|
# continue_timeout= read_timeout= write_timeout=
|
386
372
|
if http_session.respond_to?(method)
|
387
373
|
http_session.send(method, v)
|
374
|
+
elsif k.eql?('ssl_options')
|
375
|
+
# NOTE: here is a hack that allows setting SSLContext options
|
376
|
+
Aspera.assert_type(v, Array){'ssl_options'}
|
377
|
+
# more dynamic method, but more complex:
|
378
|
+
# Net::HTTP::SSL_ATTRIBUTES.push(:options) unless Net::HTTP::SSL_ATTRIBUTES.include?(:options)
|
379
|
+
# Net::HTTP::SSL_IVNAMES.push(:@options) unless Net::HTTP::SSL_IVNAMES.include?(:@options)
|
380
|
+
# Start with default options
|
381
|
+
ssl_options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options]
|
382
|
+
v.each do |opt|
|
383
|
+
case opt
|
384
|
+
when Integer
|
385
|
+
ssl_options = opt
|
386
|
+
when String
|
387
|
+
name = "OP_#{opt.start_with?('-') ? opt[1..] : opt}".upcase
|
388
|
+
raise Cli::BadArgument, "No such ssl_option: #{name}, use one of: #{OpenSSL::SSL.constants.grep(/^OP_/).map{ |c| c.to_s.sub(/^OP_/, '')}.join(', ')}" if !OpenSSL::SSL.const_defined?(name)
|
389
|
+
if opt.start_with?('-')
|
390
|
+
ssl_options &= ~OpenSSL::SSL.const_get(name)
|
391
|
+
else
|
392
|
+
ssl_options |= OpenSSL::SSL.const_get(name)
|
393
|
+
end
|
394
|
+
else
|
395
|
+
Aspera.error_unexpected_value(opt.class.name){'Expected String or Integer in ssl_options'}
|
396
|
+
end
|
397
|
+
end
|
398
|
+
# http_session.instance_variable_set(:@options, ssl_options)
|
399
|
+
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options] = ssl_options
|
388
400
|
else
|
389
401
|
Log.log.error{"no such HTTP session attribute: #{k}"}
|
390
402
|
end
|
@@ -423,7 +435,8 @@ module Aspera
|
|
423
435
|
check_date_persist = PersistencyActionOnce.new(
|
424
436
|
manager: persistency,
|
425
437
|
data: last_check_array,
|
426
|
-
id: 'version_last_check'
|
438
|
+
id: 'version_last_check'
|
439
|
+
)
|
427
440
|
# get persisted date or nil
|
428
441
|
current_date = Date.today
|
429
442
|
last_check_days = (current_date - Date.strptime(last_check_array.first, GEM_CHECK_DATE_FMT)) rescue nil
|
@@ -447,7 +460,7 @@ module Aspera
|
|
447
460
|
default_config_name = get_plugin_default_config_name(plugin_name_sym)
|
448
461
|
Log.log.debug{"add_plugin_default_preset:#{plugin_name_sym}:#{default_config_name}"}
|
449
462
|
options.add_option_preset(preset_by_name(default_config_name), 'default_plugin', override: false) unless default_config_name.nil?
|
450
|
-
return
|
463
|
+
return
|
451
464
|
end
|
452
465
|
|
453
466
|
# get the default global preset, or set default one
|
@@ -495,12 +508,12 @@ module Aspera
|
|
495
508
|
# @return the hash from name (also expands possible includes)
|
496
509
|
# @param config_name name of the preset in config file
|
497
510
|
# @param include_path used to detect and avoid include loops
|
498
|
-
def preset_by_name(config_name, include_path=[])
|
511
|
+
def preset_by_name(config_name, include_path = [])
|
499
512
|
raise Cli::Error, 'loop in include' if include_path.include?(config_name)
|
500
513
|
include_path = include_path.clone # avoid messing up if there are multiple branches
|
501
514
|
current = @config_presets
|
502
515
|
config_name.split(PRESET_DIG_SEPARATOR).each do |name|
|
503
|
-
Aspera.assert_type(current, Hash,
|
516
|
+
Aspera.assert_type(current, Hash, type: Cli::Error){"sub key: #{include_path}"}
|
504
517
|
include_path.push(name)
|
505
518
|
current = current[name]
|
506
519
|
raise Cli::Error, "No such config preset: #{include_path}" if current.nil?
|
@@ -537,7 +550,7 @@ module Aspera
|
|
537
550
|
when String
|
538
551
|
options.add_option_preset(preset_by_name(value), 'set_by_name')
|
539
552
|
else
|
540
|
-
raise 'Preset definition must be a String for preset name, or Hash for set of values'
|
553
|
+
raise BadArgument, 'Preset definition must be a String for preset name, or Hash for set of values'
|
541
554
|
end
|
542
555
|
end
|
543
556
|
|
@@ -563,12 +576,12 @@ module Aspera
|
|
563
576
|
@config_checksum_on_disk = config_checksum
|
564
577
|
end
|
565
578
|
files_to_copy = []
|
566
|
-
Log.
|
579
|
+
Log.dump(:available_presets, @config_presets, level: :trace1)
|
567
580
|
Aspera.assert_type(@config_presets, Hash){'config file YAML'}
|
568
581
|
# check there is at least the config section
|
569
582
|
Aspera.assert(@config_presets.key?(CONF_PRESET_CONFIG)){"Cannot find key: #{CONF_PRESET_CONFIG}"}
|
570
583
|
version = @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]
|
571
|
-
raise 'No version found in config section.' if version.nil?
|
584
|
+
raise Error, 'No version found in config section.' if version.nil?
|
572
585
|
Log.log.debug{"conf version: #{version}"}
|
573
586
|
# VVV if there are any conversion needed, those happen here.
|
574
587
|
# fix bug in 4.4 (creating key "true" in "default" preset)
|
@@ -598,46 +611,6 @@ module Aspera
|
|
598
611
|
raise Cli::Error, e.to_s
|
599
612
|
end
|
600
613
|
|
601
|
-
# Find a plugin, and issue the "require"
|
602
|
-
# @return [Hash] plugin info: { product: , url:, version: }
|
603
|
-
def identify_plugins_for_url
|
604
|
-
app_url = options.get_next_argument('url', mandatory: true)
|
605
|
-
check_only = options.get_next_argument('plugin name', mandatory: false)
|
606
|
-
check_only = check_only.to_sym unless check_only.nil?
|
607
|
-
found_apps = []
|
608
|
-
my_self_plugin_sym = self.class.name.split('::').last.downcase.to_sym
|
609
|
-
PluginFactory.instance.plugin_list.each do |plugin_name_sym|
|
610
|
-
# no detection for internal plugin
|
611
|
-
next if plugin_name_sym.eql?(my_self_plugin_sym)
|
612
|
-
next if check_only && !check_only.eql?(plugin_name_sym)
|
613
|
-
# load plugin class
|
614
|
-
detect_plugin_class = PluginFactory.instance.plugin_class(plugin_name_sym)
|
615
|
-
# requires detection method
|
616
|
-
next unless detect_plugin_class.respond_to?(:detect)
|
617
|
-
detection_info = nil
|
618
|
-
begin
|
619
|
-
Log.log.debug{"detecting #{plugin_name_sym} at #{app_url}"}
|
620
|
-
formatter.long_operation_running("#{plugin_name_sym}\r")
|
621
|
-
detection_info = detect_plugin_class.detect(app_url)
|
622
|
-
rescue OpenSSL::SSL::SSLError => e
|
623
|
-
Log.log.warn(e.message)
|
624
|
-
Log.log.warn('Use option --insecure=yes to allow unchecked certificate') if e.message.include?('cert')
|
625
|
-
rescue StandardError => e
|
626
|
-
Log.log.debug{"detect error: [#{e.class}] #{e}"}
|
627
|
-
next
|
628
|
-
end
|
629
|
-
next if detection_info.nil?
|
630
|
-
Aspera.assert_type(detection_info, Hash)
|
631
|
-
Aspera.assert_type(detection_info[:url], String) if detection_info.key?(:url)
|
632
|
-
app_name = detect_plugin_class.respond_to?(:application_name) ? detect_plugin_class.application_name : detect_plugin_class.name.split('::').last
|
633
|
-
# if there is a redirect, then the detector can override the url.
|
634
|
-
found_apps.push({product: plugin_name_sym, name: app_name, url: app_url, version: 'unknown'}.merge(detection_info))
|
635
|
-
end
|
636
|
-
raise "No known application found at #{app_url}" if found_apps.empty?
|
637
|
-
Aspera.assert(found_apps.all?{ |a| a.keys.all?(Symbol)})
|
638
|
-
return found_apps
|
639
|
-
end
|
640
|
-
|
641
614
|
def execute_connect_action
|
642
615
|
command = options.get_next_command(%i[list info version])
|
643
616
|
if %i[info version].include?(command)
|
@@ -686,12 +659,12 @@ module Aspera
|
|
686
659
|
set_global_default(:ascp_path, ascp_path)
|
687
660
|
return Main.result_nothing
|
688
661
|
when :show
|
689
|
-
return Main.
|
662
|
+
return Main.result_text(Ascp::Installation.instance.path(:ascp))
|
690
663
|
when :info
|
691
664
|
# collect info from ascp executable
|
692
665
|
data = Ascp::Installation.instance.ascp_info
|
693
666
|
# add command line transfer spec
|
694
|
-
data['ts'] = transfer.
|
667
|
+
data['ts'] = transfer.option_transfer_spec
|
695
668
|
# add keys
|
696
669
|
DataRepository::ELEMENTS.each_with_object(data){ |i, h| h[i.to_s] = DataRepository.instance.item(i)}
|
697
670
|
# declare those as secrets
|
@@ -715,10 +688,8 @@ module Aspera
|
|
715
688
|
n, v = Ascp::Installation.instance.install_sdk(url: options.get_option(:sdk_url, mandatory: true), version: version)
|
716
689
|
return Main.result_status("Installed #{n} version #{v}")
|
717
690
|
when :spec
|
718
|
-
|
719
|
-
|
720
|
-
fields: Transfer::SpecDoc::TABLE_COLUMNS.map(&:to_s)
|
721
|
-
)
|
691
|
+
fields, data = Transfer::SpecDoc.man_table(Formatter)
|
692
|
+
return Main.result_object_list(data, fields: fields.map(&:to_s))
|
722
693
|
when :schema
|
723
694
|
schema = Transfer::Spec::SCHEMA.merge({'$comment'=>'DO NOT EDIT, this file was generated from the YAML.'})
|
724
695
|
agent = options.get_next_argument('transfer agent name', mandatory: false)
|
@@ -772,7 +743,7 @@ module Aspera
|
|
772
743
|
raise "no such preset: #{name}" if PRESET_EXIST_ACTIONS.include?(action) && !@config_presets.key?(name)
|
773
744
|
case action
|
774
745
|
when :list
|
775
|
-
return Main.result_value_list(@config_presets.keys, 'name')
|
746
|
+
return Main.result_value_list(@config_presets.keys, name: 'name')
|
776
747
|
when :overview
|
777
748
|
# display process modifies the value (hide secrets): we do not want to save removed secrets
|
778
749
|
data = self.class.deep_clone(@config_presets)
|
@@ -809,9 +780,7 @@ module Aspera
|
|
809
780
|
return Main.result_nothing
|
810
781
|
when :initialize
|
811
782
|
config_value = options.get_next_argument('extended value', validation: Hash)
|
812
|
-
if @config_presets.key?(name)
|
813
|
-
Log.log.warn{"configuration already exists: #{name}, overwriting"}
|
814
|
-
end
|
783
|
+
Log.log.warn{"configuration already exists: #{name}, overwriting"} if @config_presets.key?(name)
|
815
784
|
@config_presets[name] = config_value
|
816
785
|
return Main.result_status("Modified: #{@option_config_file}")
|
817
786
|
when :update
|
@@ -834,7 +803,7 @@ module Aspera
|
|
834
803
|
url = options.get_option(:url, mandatory: true)
|
835
804
|
user = options.get_option(:username, mandatory: true)
|
836
805
|
result = lookup_preset(url: url, username: user)
|
837
|
-
raise 'no such config found' if result.nil?
|
806
|
+
raise Error, 'no such config found' if result.nil?
|
838
807
|
return Main.result_single_object(result)
|
839
808
|
when :secure
|
840
809
|
identifier = options.get_next_argument('config name', mandatory: false)
|
@@ -901,7 +870,7 @@ module Aspera
|
|
901
870
|
when :preset # newer syntax
|
902
871
|
return execute_preset
|
903
872
|
when :open
|
904
|
-
Environment.open_editor(@option_config_file.to_s)
|
873
|
+
Environment.instance.open_editor(@option_config_file.to_s)
|
905
874
|
return Main.result_nothing
|
906
875
|
when :documentation
|
907
876
|
section = options.get_next_argument('private key file path', mandatory: false)
|
@@ -910,12 +879,12 @@ module Aspera
|
|
910
879
|
return Main.result_nothing
|
911
880
|
when :genkey # generate new rsa key
|
912
881
|
private_key_path = options.get_next_argument('private key file path')
|
913
|
-
private_key_length = options.get_next_argument('size in bits', mandatory: false, validation: Integer, default: DEFAULT_PRIV_KEY_LENGTH)
|
914
|
-
|
882
|
+
private_key_length = options.get_next_argument('size in bits', mandatory: false, validation: Integer, default: OAuth::Jwt::DEFAULT_PRIV_KEY_LENGTH)
|
883
|
+
OAuth::Jwt.generate_rsa_private_key(path: private_key_path, length: private_key_length)
|
915
884
|
return Main.result_status("Generated #{private_key_length} bit RSA key: #{private_key_path}")
|
916
885
|
when :pubkey # get pub key
|
917
886
|
private_key_pem = options.get_next_argument('private key PEM value')
|
918
|
-
return Main.
|
887
|
+
return Main.result_text(OpenSSL::PKey::RSA.new(private_key_pem).public_key.to_s)
|
919
888
|
when :remote_certificate
|
920
889
|
cert_action = options.get_next_command(%i[chain only name])
|
921
890
|
remote_url = options.get_next_argument('remote URL')
|
@@ -923,20 +892,18 @@ module Aspera
|
|
923
892
|
raise "No certificate found for #{remote_url}" unless remote_chain&.first
|
924
893
|
case cert_action
|
925
894
|
when :chain
|
926
|
-
return Main.
|
895
|
+
return Main.result_text(remote_chain.map(&:to_pem).join("\n"))
|
927
896
|
when :only
|
928
|
-
return Main.
|
897
|
+
return Main.result_text(remote_chain.first.to_pem)
|
929
898
|
when :name
|
930
|
-
return Main.
|
899
|
+
return Main.result_text(remote_chain.first.subject.to_a.find{ |name, _, _| name == 'CN'}[1])
|
931
900
|
end
|
932
901
|
when :echo # display the content of a value given on command line
|
933
902
|
return Main.result_auto(options.get_next_argument('value', validation: nil))
|
934
903
|
when :download
|
935
904
|
file_url = options.get_next_argument('source URL').chomp
|
936
905
|
file_dest = options.get_next_argument('file path', mandatory: false)
|
937
|
-
if file_dest.nil?
|
938
|
-
file_dest = File.join(transfer.destination_folder(Transfer::Spec::DIRECTION_RECEIVE), file_url.gsub(%r{.*/}, ''))
|
939
|
-
end
|
906
|
+
file_dest = File.join(transfer.destination_folder(Transfer::Spec::DIRECTION_RECEIVE), file_url.gsub(%r{.*/}, '')) if file_dest.nil?
|
940
907
|
formatter.display_status("Downloading: #{file_url}")
|
941
908
|
Rest.new(base_url: file_url).call(operation: 'GET', save_to_file: file_dest)
|
942
909
|
return Main.result_status("Saved to: #{file_dest}")
|
@@ -990,27 +957,27 @@ module Aspera
|
|
990
957
|
# interactive mode
|
991
958
|
options.ask_missing_mandatory = true
|
992
959
|
# detect plugins by url and optional query
|
993
|
-
apps = identify_plugins_for_url.freeze
|
960
|
+
apps = @wizard.identify_plugins_for_url.freeze
|
994
961
|
return Main.result_object_list(apps) if action.eql?(:detect)
|
995
|
-
return
|
962
|
+
return @wizard.find(apps)
|
996
963
|
when :coffee
|
997
|
-
return Main.result_image(
|
964
|
+
return Main.result_image(COFFEE_IMAGE_URL)
|
998
965
|
when :image
|
999
|
-
return Main.result_image(options.get_next_argument('image
|
966
|
+
return Main.result_image(options.get_next_argument('image URI or blob'))
|
1000
967
|
when :ascp
|
1001
968
|
execute_action_ascp
|
1002
969
|
when :transferd
|
1003
970
|
execute_action_transferd
|
1004
971
|
when :gem
|
1005
972
|
case options.get_next_command(%i[path version name])
|
1006
|
-
when :path then return Main.
|
1007
|
-
when :version then return Main.
|
1008
|
-
when :name then return Main.
|
973
|
+
when :path then return Main.result_text(self.class.gem_src_root)
|
974
|
+
when :version then return Main.result_text(Cli::VERSION)
|
975
|
+
when :name then return Main.result_text(Info::GEM_NAME)
|
1009
976
|
end
|
1010
977
|
when :folder
|
1011
|
-
return Main.
|
978
|
+
return Main.result_text(@main_folder)
|
1012
979
|
when :file
|
1013
|
-
return Main.
|
980
|
+
return Main.result_text(@option_config_file)
|
1014
981
|
when :email_test
|
1015
982
|
send_email_template(email_template_default: EMAIL_TEST_TEMPLATE)
|
1016
983
|
return Main.result_nothing
|
@@ -1020,7 +987,7 @@ module Aspera
|
|
1020
987
|
# ensure fpac was provided
|
1021
988
|
options.get_option(:fpac, mandatory: true)
|
1022
989
|
server_url = options.get_next_argument('server url')
|
1023
|
-
return Main.
|
990
|
+
return Main.result_text(@pac_exec.get_proxies(server_url))
|
1024
991
|
when :check_update
|
1025
992
|
return Main.result_single_object(check_gem_version)
|
1026
993
|
when :initdemo
|
@@ -1047,101 +1014,11 @@ module Aspera
|
|
1047
1014
|
when :vault then execute_vault
|
1048
1015
|
when :test then return execute_test
|
1049
1016
|
when :platform
|
1050
|
-
return Main.
|
1017
|
+
return Main.result_text(Environment.instance.architecture)
|
1051
1018
|
else Aspera.error_unreachable_line
|
1052
1019
|
end
|
1053
1020
|
end
|
1054
1021
|
|
1055
|
-
def wizard_find(apps)
|
1056
|
-
identification = if apps.length.eql?(1)
|
1057
|
-
Log.log.debug{"Detected: #{identification}"}
|
1058
|
-
apps.first
|
1059
|
-
else
|
1060
|
-
formatter.display_status('Multiple applications detected, please select from:')
|
1061
|
-
formatter.display_results(type: :object_list, data: apps, fields: %w[product url version])
|
1062
|
-
answer = options.prompt_user_input_in_list('product', apps.map{ |a| a[:product]})
|
1063
|
-
apps.find{ |a| a[:product].eql?(answer)}
|
1064
|
-
end
|
1065
|
-
wiz_preset_name = options.get_next_argument('preset name', default: '')
|
1066
|
-
Log.log.debug{Log.dump(:identification, identification)}
|
1067
|
-
wiz_url = identification[:url]
|
1068
|
-
formatter.display_status("Using: #{identification[:name]} at #{wiz_url}".bold)
|
1069
|
-
# set url for instantiation of plugin
|
1070
|
-
options.add_option_preset({url: wiz_url}, 'wizard')
|
1071
|
-
# instantiate plugin: command line options will be known and wizard can be called
|
1072
|
-
wiz_plugin_class = PluginFactory.instance.plugin_class(identification[:product])
|
1073
|
-
Aspera.assert(wiz_plugin_class.respond_to?(:wizard), exception_class: Cli::BadArgument) do
|
1074
|
-
"Detected: #{identification[:product]}, but this application has no wizard"
|
1075
|
-
end
|
1076
|
-
# instantiate plugin: command line options will be known, e.g. private_key
|
1077
|
-
plugin_instance = wiz_plugin_class.new(**init_params)
|
1078
|
-
wiz_params = {
|
1079
|
-
object: plugin_instance
|
1080
|
-
}
|
1081
|
-
# is private key needed ?
|
1082
|
-
if options.known_options.key?(:private_key) &&
|
1083
|
-
(!wiz_plugin_class.respond_to?(:private_key_required?) || wiz_plugin_class.private_key_required?(wiz_url))
|
1084
|
-
# lets see if path to priv key is provided
|
1085
|
-
private_key_path = options.get_option(:key_path)
|
1086
|
-
# give a chance to provide
|
1087
|
-
if private_key_path.nil?
|
1088
|
-
formatter.display_status('Please provide the path to your private RSA key, or nothing to generate one:')
|
1089
|
-
private_key_path = options.get_option(:key_path, mandatory: true).to_s
|
1090
|
-
end
|
1091
|
-
# else generate path
|
1092
|
-
if private_key_path.empty?
|
1093
|
-
private_key_path = File.join(@main_folder, DEFAULT_PRIV_KEY_FILENAME)
|
1094
|
-
end
|
1095
|
-
if File.exist?(private_key_path)
|
1096
|
-
formatter.display_status('Using existing key:')
|
1097
|
-
else
|
1098
|
-
formatter.display_status("Generating #{DEFAULT_PRIV_KEY_LENGTH} bit RSA key...")
|
1099
|
-
self.class.generate_rsa_private_key(path: private_key_path)
|
1100
|
-
formatter.display_status('Created key:')
|
1101
|
-
end
|
1102
|
-
formatter.display_status(private_key_path)
|
1103
|
-
private_key_pem = File.read(private_key_path)
|
1104
|
-
options.set_option(:private_key, private_key_pem)
|
1105
|
-
wiz_params[:private_key_path] = private_key_path
|
1106
|
-
wiz_params[:pub_key_pem] = OpenSSL::PKey::RSA.new(private_key_pem).public_key.to_s
|
1107
|
-
end
|
1108
|
-
Log.log.debug{Log.dump(:wiz_params, wiz_params)}
|
1109
|
-
# finally, call the wizard
|
1110
|
-
wizard_result = wiz_plugin_class.wizard(**wiz_params)
|
1111
|
-
Log.log.debug{"wizard result: #{wizard_result}"}
|
1112
|
-
Aspera.assert(WIZARD_RESULT_KEYS.eql?(wizard_result.keys.sort)){"missing or extra keys in wizard result: #{wizard_result.keys}"}
|
1113
|
-
# get preset name from user or default
|
1114
|
-
if wiz_preset_name.empty?
|
1115
|
-
elements = [
|
1116
|
-
identification[:product],
|
1117
|
-
URI.parse(wiz_url).host
|
1118
|
-
]
|
1119
|
-
elements.push(options.get_option(:username, mandatory: true)) unless wizard_result[:preset_value].key?(:link) rescue nil
|
1120
|
-
wiz_preset_name = elements.join('_').strip.downcase.gsub(/[^a-z0-9]/, '_').squeeze('_')
|
1121
|
-
end
|
1122
|
-
# test mode does not change conf file
|
1123
|
-
return Main.result_single_object(wizard_result) if options.get_option(:test_mode)
|
1124
|
-
# Write configuration file
|
1125
|
-
formatter.display_status("Preparing preset: #{wiz_preset_name}")
|
1126
|
-
# init defaults if necessary
|
1127
|
-
@config_presets[CONF_PRESET_DEFAULTS] ||= {}
|
1128
|
-
option_override = options.get_option(:override, mandatory: true)
|
1129
|
-
raise Cli::Error, "A default configuration already exists for plugin '#{identification[:product]}' (use --override=yes or --default=no)" \
|
1130
|
-
if !option_override && options.get_option(:default, mandatory: true) && @config_presets[CONF_PRESET_DEFAULTS].key?(identification[:product])
|
1131
|
-
raise Cli::Error, "Preset already exists: #{wiz_preset_name} (use --override=yes or --id=<name>)" \
|
1132
|
-
if !option_override && @config_presets.key?(wiz_preset_name)
|
1133
|
-
@config_presets[wiz_preset_name] = wizard_result[:preset_value].stringify_keys
|
1134
|
-
test_args = wizard_result[:test_args]
|
1135
|
-
if options.get_option(:default, mandatory: true)
|
1136
|
-
formatter.display_status("Setting config preset as default for #{identification[:product]}")
|
1137
|
-
@config_presets[CONF_PRESET_DEFAULTS][identification[:product].to_s] = wiz_preset_name
|
1138
|
-
else
|
1139
|
-
test_args = "-P#{wiz_preset_name} #{test_args}"
|
1140
|
-
end
|
1141
|
-
# TODO: actually test the command
|
1142
|
-
return Main.result_status("You can test with:\n#{Info::CMD_NAME} #{identification[:product]} #{test_args}")
|
1143
|
-
end
|
1144
|
-
|
1145
1022
|
# @return [Hash] email server setting with defaults if not defined
|
1146
1023
|
def email_settings
|
1147
1024
|
smtp = options.get_option(:smtp, mandatory: true)
|
@@ -1193,7 +1070,7 @@ module Aspera
|
|
1193
1070
|
end
|
1194
1071
|
# execute template
|
1195
1072
|
msg_with_headers = ERB.new(notify_template).result(template_binding)
|
1196
|
-
Log.
|
1073
|
+
Log.dump(:msg_with_headers, msg_with_headers)
|
1197
1074
|
require 'net/smtp'
|
1198
1075
|
smtp = Net::SMTP.new(mail_conf[:server], mail_conf[:port])
|
1199
1076
|
smtp.enable_starttls if mail_conf[:tls]
|
@@ -1207,7 +1084,7 @@ module Aspera
|
|
1207
1084
|
# Save current configuration to config file
|
1208
1085
|
# return true if file was saved
|
1209
1086
|
def save_config_file_if_needed
|
1210
|
-
raise 'no configuration loaded' if @config_presets.nil?
|
1087
|
+
raise Error, 'no configuration loaded' if @config_presets.nil?
|
1211
1088
|
current_checksum = config_checksum
|
1212
1089
|
return false if @config_checksum_on_disk.eql?(current_checksum)
|
1213
1090
|
FileUtils.mkdir_p(@main_folder)
|
@@ -1225,7 +1102,7 @@ module Aspera
|
|
1225
1102
|
Aspera.assert(!@config_presets.nil?){'config_presets shall be defined'}
|
1226
1103
|
if !@use_plugin_defaults
|
1227
1104
|
Log.log.debug('skip default config')
|
1228
|
-
return
|
1105
|
+
return
|
1229
1106
|
end
|
1230
1107
|
if @config_presets.key?(CONF_PRESET_DEFAULTS) &&
|
1231
1108
|
@config_presets[CONF_PRESET_DEFAULTS].key?(plugin_name_sym.to_s)
|
@@ -1241,7 +1118,7 @@ module Aspera
|
|
1241
1118
|
raise Cli::Error, "Config name [#{default_config_name}] must be a hash, check config file." if !@config_presets[default_config_name].is_a?(Hash)
|
1242
1119
|
return default_config_name
|
1243
1120
|
end
|
1244
|
-
return
|
1121
|
+
return
|
1245
1122
|
end
|
1246
1123
|
|
1247
1124
|
# @return [Hash] result of execution of vault command
|
@@ -1256,11 +1133,7 @@ module Aspera
|
|
1256
1133
|
when :show
|
1257
1134
|
return Main.result_single_object(vault.get(label: options.get_next_argument('label')))
|
1258
1135
|
when :create
|
1259
|
-
|
1260
|
-
info = options.get_next_argument('info', validation: Hash)
|
1261
|
-
info = info.symbolize_keys
|
1262
|
-
info[:label] = label
|
1263
|
-
vault.set(info)
|
1136
|
+
vault.set(options.get_next_argument('info', validation: Hash).symbolize_keys)
|
1264
1137
|
return Main.result_status('Secret added')
|
1265
1138
|
when :delete
|
1266
1139
|
label_to_delete = options.get_next_argument('label')
|
@@ -1276,7 +1149,7 @@ module Aspera
|
|
1276
1149
|
# @return [String] value from vault matching <name>.<param>
|
1277
1150
|
def vault_value(name)
|
1278
1151
|
m = name.split('.')
|
1279
|
-
raise 'vault name shall match <name>.<param>' unless m.length.eql?(2)
|
1152
|
+
raise BadArgument, 'vault name shall match <name>.<param>' unless m.length.eql?(2)
|
1280
1153
|
# this raise exception if label not found:
|
1281
1154
|
info = vault.get(label: m[0])
|
1282
1155
|
value = info[m[1].to_sym]
|
@@ -1298,6 +1171,7 @@ module Aspera
|
|
1298
1171
|
)
|
1299
1172
|
end
|
1300
1173
|
|
1174
|
+
# Artifically raise an exception for tests
|
1301
1175
|
def execute_test
|
1302
1176
|
case options.get_next_command(%i[throw web])
|
1303
1177
|
when :throw
|
@@ -1305,18 +1179,20 @@ module Aspera
|
|
1305
1179
|
# options
|
1306
1180
|
exception_class_name = options.get_next_argument('exception class name', mandatory: true)
|
1307
1181
|
exception_text = options.get_next_argument('exception text', mandatory: true)
|
1308
|
-
|
1309
|
-
Aspera.assert(
|
1310
|
-
raise
|
1182
|
+
type = Object.const_get(exception_class_name)
|
1183
|
+
Aspera.assert(type <= Exception){"#{type} is not an exception: #{type.class}"}
|
1184
|
+
raise type, exception_text
|
1311
1185
|
when :web
|
1312
1186
|
end
|
1313
1187
|
end
|
1314
1188
|
|
1315
1189
|
# version of URL without trailing "/" and removing default port
|
1316
1190
|
def canonical_url(url)
|
1317
|
-
url.
|
1191
|
+
url.chomp('/').sub(%r{^(https://[^/]+):443$}, '\1')
|
1318
1192
|
end
|
1319
1193
|
|
1194
|
+
# Look for a preset that has the corresponding URL and username
|
1195
|
+
# @return the first one matching
|
1320
1196
|
def lookup_preset(url:, username:)
|
1321
1197
|
# remove extra info to maximize match
|
1322
1198
|
url = canonical_url(url)
|
@@ -1329,6 +1205,8 @@ module Aspera
|
|
1329
1205
|
nil
|
1330
1206
|
end
|
1331
1207
|
|
1208
|
+
# Lookup the corresponding secret for the given URL and usernames
|
1209
|
+
# @raise Exception if mandatory and not found
|
1332
1210
|
def lookup_secret(url:, username:, mandatory: false)
|
1333
1211
|
secret = options.get_option(:secret)
|
1334
1212
|
if secret.nil?
|