aspera-cli 4.24.2 → 4.25.0.pre
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 +1064 -758
- data/CONTRIBUTING.md +43 -100
- data/README.md +671 -419
- data/lib/aspera/api/aoc.rb +71 -43
- data/lib/aspera/api/cos_node.rb +3 -2
- data/lib/aspera/api/faspex.rb +6 -5
- data/lib/aspera/api/node.rb +10 -12
- data/lib/aspera/ascmd.rb +1 -2
- data/lib/aspera/ascp/installation.rb +53 -39
- data/lib/aspera/assert.rb +25 -3
- data/lib/aspera/cli/error.rb +4 -2
- data/lib/aspera/cli/extended_value.rb +84 -60
- data/lib/aspera/cli/formatter.rb +55 -22
- data/lib/aspera/cli/main.rb +21 -14
- data/lib/aspera/cli/manager.rb +348 -247
- data/lib/aspera/cli/plugins/alee.rb +3 -3
- data/lib/aspera/cli/plugins/aoc.rb +70 -14
- data/lib/aspera/cli/plugins/base.rb +57 -49
- data/lib/aspera/cli/plugins/config.rb +69 -84
- data/lib/aspera/cli/plugins/console.rb +13 -8
- data/lib/aspera/cli/plugins/cos.rb +1 -1
- data/lib/aspera/cli/plugins/faspex.rb +32 -26
- data/lib/aspera/cli/plugins/faspex5.rb +45 -43
- data/lib/aspera/cli/plugins/faspio.rb +5 -5
- data/lib/aspera/cli/plugins/httpgw.rb +1 -1
- data/lib/aspera/cli/plugins/node.rb +131 -120
- data/lib/aspera/cli/plugins/oauth.rb +1 -1
- data/lib/aspera/cli/plugins/orchestrator.rb +114 -32
- data/lib/aspera/cli/plugins/preview.rb +26 -46
- data/lib/aspera/cli/plugins/server.rb +6 -8
- data/lib/aspera/cli/plugins/shares.rb +27 -32
- data/lib/aspera/cli/sync_actions.rb +49 -38
- data/lib/aspera/cli/transfer_agent.rb +16 -34
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +8 -5
- data/lib/aspera/command_line_builder.rb +20 -17
- data/lib/aspera/coverage.rb +1 -1
- data/lib/aspera/environment.rb +41 -34
- data/lib/aspera/faspex_gw.rb +1 -1
- data/lib/aspera/keychain/factory.rb +1 -2
- data/lib/aspera/markdown.rb +31 -0
- data/lib/aspera/nagios.rb +6 -5
- data/lib/aspera/oauth/base.rb +17 -27
- data/lib/aspera/oauth/factory.rb +1 -1
- data/lib/aspera/oauth/url_json.rb +2 -1
- data/lib/aspera/preview/file_types.rb +23 -37
- data/lib/aspera/products/connect.rb +3 -3
- data/lib/aspera/rest.rb +51 -39
- data/lib/aspera/rest_error_analyzer.rb +4 -4
- data/lib/aspera/ssh.rb +5 -2
- data/lib/aspera/ssl.rb +41 -0
- data/lib/aspera/sync/conf.schema.yaml +182 -34
- data/lib/aspera/sync/database.rb +2 -1
- data/lib/aspera/sync/operations.rb +125 -69
- data/lib/aspera/transfer/parameters.rb +3 -4
- data/lib/aspera/transfer/spec.rb +2 -3
- data/lib/aspera/transfer/spec.schema.yaml +48 -18
- data/lib/aspera/transfer/spec_doc.rb +14 -14
- data/lib/aspera/uri_reader.rb +1 -1
- data/lib/transferd_pb.rb +2 -2
- data.tar.gz.sig +0 -0
- metadata +19 -6
- metadata.gz.sig +3 -2
|
@@ -10,6 +10,7 @@ require 'aspera/cli/formatter'
|
|
|
10
10
|
require 'aspera/cli/info'
|
|
11
11
|
require 'aspera/cli/transfer_progress'
|
|
12
12
|
require 'aspera/cli/wizard'
|
|
13
|
+
require 'aspera/cli/sync_actions'
|
|
13
14
|
require 'aspera/ascp/installation'
|
|
14
15
|
require 'aspera/sync/operations'
|
|
15
16
|
require 'aspera/products/transferd'
|
|
@@ -29,6 +30,7 @@ require 'aspera/oauth/jwt'
|
|
|
29
30
|
require 'aspera/log'
|
|
30
31
|
require 'aspera/assert'
|
|
31
32
|
require 'aspera/oauth'
|
|
33
|
+
require 'aspera/ssl'
|
|
32
34
|
require 'openssl'
|
|
33
35
|
require 'open3'
|
|
34
36
|
require 'date'
|
|
@@ -39,6 +41,8 @@ module Aspera
|
|
|
39
41
|
module Plugins
|
|
40
42
|
# Manage the CLI config file
|
|
41
43
|
class Config < Base
|
|
44
|
+
include SyncActions
|
|
45
|
+
|
|
42
46
|
class << self
|
|
43
47
|
# Folder containing plugins in the gem's main folder
|
|
44
48
|
def gem_plugins_folder
|
|
@@ -89,7 +93,7 @@ module Aspera
|
|
|
89
93
|
@option_cache_tokens = true
|
|
90
94
|
@main_folder = nil
|
|
91
95
|
@option_config_file = nil
|
|
92
|
-
# Store is used for ruby https
|
|
96
|
+
# Store is used for ruby https (OpenSSL::X509::Store)
|
|
93
97
|
@certificate_store = nil
|
|
94
98
|
# Paths are used for ascp
|
|
95
99
|
@certificate_paths = nil
|
|
@@ -98,7 +102,6 @@ module Aspera
|
|
|
98
102
|
options.declare(
|
|
99
103
|
:home, 'Home folder for tool',
|
|
100
104
|
handler: {o: self, m: :main_folder},
|
|
101
|
-
types: String,
|
|
102
105
|
default: self.class.default_app_main_folder(app_name: Info::CMD_NAME)
|
|
103
106
|
)
|
|
104
107
|
options.parse_options!
|
|
@@ -118,65 +121,49 @@ module Aspera
|
|
|
118
121
|
# Read config file (set @config_presets)
|
|
119
122
|
read_config_file
|
|
120
123
|
# Add preset handler (needed for smtp)
|
|
121
|
-
ExtendedValue.instance.
|
|
122
|
-
ExtendedValue.instance.
|
|
124
|
+
ExtendedValue.instance.on(EXTEND_PRESET){ |v| preset_by_name(v)}
|
|
125
|
+
ExtendedValue.instance.on(EXTEND_VAULT){ |v| vault_value(v)}
|
|
126
|
+
ExtendedValue.instance.on(EXTEND_ARGS){ |v| options.args_as_extended(v)}
|
|
123
127
|
# Load defaults before it can be overridden
|
|
124
128
|
add_plugin_default_preset(CONF_GLOBAL_SYM)
|
|
125
129
|
# Vault options
|
|
126
130
|
options.declare(:secret, 'Secret for access keys')
|
|
127
|
-
options.declare(:vault, 'Vault for secrets',
|
|
131
|
+
options.declare(:vault, 'Vault for secrets', allowed: Hash)
|
|
128
132
|
options.declare(:vault_password, 'Vault password')
|
|
129
133
|
options.parse_options!
|
|
130
134
|
# Declare generic plugin options only after handlers are declared
|
|
131
135
|
Base.declare_options(options)
|
|
132
136
|
# Configuration options
|
|
133
|
-
options.declare(:no_default, 'Do not load default configuration for plugin',
|
|
137
|
+
options.declare(:no_default, 'Do not load default configuration for plugin', allowed: Allowed::TYPES_NONE, short: 'N'){@use_plugin_defaults = false}
|
|
134
138
|
options.declare(:preset, 'Load the named option preset from current config file', short: 'P', handler: {o: self, m: :option_preset})
|
|
135
|
-
options.declare(:version_check_days, 'Period in days to check new version (zero to disable)',
|
|
139
|
+
options.declare(:version_check_days, 'Period in days to check new version (zero to disable)', allowed: Allowed::TYPES_INTEGER, default: DEFAULT_CHECK_NEW_VERSION_DAYS)
|
|
136
140
|
options.declare(:plugin_folder, 'Folder where to find additional plugins', handler: {o: self, m: :option_plugin_folder})
|
|
137
141
|
# Declare wizard options
|
|
138
142
|
@wizard = Wizard.new(self, @main_folder)
|
|
139
143
|
# Transfer SDK options
|
|
140
|
-
options.declare(:ascp_path, 'Ascp: Path to ascp', handler: {o: Ascp::Installation.instance, m: :ascp_path})
|
|
141
|
-
options.declare(:use_product, 'Ascp: Use ascp from specified product', handler: {o: self, m: :option_use_product})
|
|
142
144
|
options.declare(:sdk_url, 'Ascp: URL to get Aspera Transfer Executables', default: SpecialValues::DEF)
|
|
143
|
-
options.
|
|
144
|
-
|
|
145
|
-
options.declare(:
|
|
145
|
+
options.parse_options!
|
|
146
|
+
set_sdk_dir
|
|
147
|
+
options.declare(:ascp_path, 'Ascp: Path to ascp (or product with "product:")', handler: {o: Ascp::Installation.instance, m: :ascp_path}, default: "#{Ascp::Installation::USE_PRODUCT_PREFIX}#{Ascp::Installation::FIRST_FOUND}")
|
|
148
|
+
options.declare(:locations_url, 'Ascp: URL to get download locations of Aspera Transfer Daemon', handler: {o: Ascp::Installation.instance, m: :transferd_urls})
|
|
149
|
+
options.declare(:sdk_folder, 'Ascp: SDK installation folder path', handler: {o: Products::Transferd, m: :sdk_directory})
|
|
150
|
+
options.declare(:progress_bar, 'Display progress bar', allowed: Allowed::TYPES_BOOLEAN, default: Environment.terminal?)
|
|
146
151
|
# Email options
|
|
147
|
-
options.declare(:smtp, 'Email: SMTP configuration',
|
|
152
|
+
options.declare(:smtp, 'Email: SMTP configuration', allowed: Hash)
|
|
148
153
|
options.declare(:notify_to, 'Email: Recipient for notification of transfers')
|
|
149
154
|
options.declare(:notify_template, 'Email: ERB template for notification of transfers')
|
|
150
155
|
# HTTP options
|
|
151
|
-
options.declare(:insecure, 'HTTP/S: Do not validate any certificate',
|
|
152
|
-
options.declare(:ignore_certificate, 'HTTP/S: Do not validate certificate for these URLs',
|
|
153
|
-
options.declare(:warn_insecure, 'HTTP/S: Issue a warning if certificate is ignored',
|
|
154
|
-
options.declare(:cert_stores, 'HTTP/S: List of folder with trusted certificates',
|
|
155
|
-
options.declare(:http_options, 'HTTP/S: Options for HTTP/S socket',
|
|
156
|
-
options.declare(:http_proxy, 'HTTP/S: URL for proxy with optional credentials',
|
|
157
|
-
options.declare(:cache_tokens, 'Save and reuse OAuth tokens',
|
|
156
|
+
options.declare(:insecure, 'HTTP/S: Do not validate any certificate', allowed: Allowed::TYPES_BOOLEAN, handler: {o: self, m: :option_insecure}, default: false)
|
|
157
|
+
options.declare(:ignore_certificate, 'HTTP/S: Do not validate certificate for these URLs', allowed: [Array, NilClass], handler: {o: self, m: :option_ignore_cert_host_port})
|
|
158
|
+
options.declare(:warn_insecure, 'HTTP/S: Issue a warning if certificate is ignored', allowed: Allowed::TYPES_BOOLEAN, handler: {o: self, m: :option_warn_insecure_cert}, default: true)
|
|
159
|
+
options.declare(:cert_stores, 'HTTP/S: List of folder with trusted certificates', allowed: Allowed::TYPES_STRING_ARRAY, handler: {o: self, m: :trusted_cert_locations})
|
|
160
|
+
options.declare(:http_options, 'HTTP/S: Options for HTTP/S socket', allowed: Hash, handler: {o: self, m: :option_http_options}, default: {})
|
|
161
|
+
options.declare(:http_proxy, 'HTTP/S: URL for proxy with optional credentials', handler: {o: self, m: :option_http_proxy})
|
|
162
|
+
options.declare(:cache_tokens, 'Save and reuse OAuth tokens', allowed: Allowed::TYPES_BOOLEAN, handler: {o: self, m: :option_cache_tokens})
|
|
158
163
|
options.declare(:fpac, 'Proxy auto configuration script')
|
|
159
|
-
options.declare(:proxy_credentials, 'HTTP proxy credentials for fpac: user, password',
|
|
164
|
+
options.declare(:proxy_credentials, 'HTTP proxy credentials for fpac: user, password', allowed: [Array, NilClass])
|
|
160
165
|
options.parse_options!
|
|
161
166
|
@progress_bar = TransferProgress.new if options.get_option(:progress_bar)
|
|
162
|
-
# Check SDK folder is set or not, for compatibility, we check in two places
|
|
163
|
-
sdk_dir = Products::Transferd.sdk_directory rescue nil
|
|
164
|
-
if sdk_dir.nil?
|
|
165
|
-
@sdk_default_location = true
|
|
166
|
-
Log.log.debug('SDK folder is not set, checking default')
|
|
167
|
-
# New location
|
|
168
|
-
sdk_dir = self.class.default_app_main_folder(app_name: TRANSFERD_APP_NAME)
|
|
169
|
-
Log.log.debug{"Checking: #{sdk_dir}"}
|
|
170
|
-
if !Dir.exist?(sdk_dir)
|
|
171
|
-
Log.log.debug{"No such folder: #{sdk_dir}"}
|
|
172
|
-
# Former location
|
|
173
|
-
former_sdk_folder = File.join(self.class.default_app_main_folder(app_name: Info::CMD_NAME), TRANSFERD_APP_NAME)
|
|
174
|
-
Log.log.debug{"Checking: #{former_sdk_folder}"}
|
|
175
|
-
sdk_dir = former_sdk_folder if Dir.exist?(former_sdk_folder)
|
|
176
|
-
end
|
|
177
|
-
Log.log.debug{"Using: #{sdk_dir}"}
|
|
178
|
-
Products::Transferd.sdk_directory = sdk_dir
|
|
179
|
-
end
|
|
180
167
|
pac_script = options.get_option(:fpac)
|
|
181
168
|
# Create PAC executor
|
|
182
169
|
if !pac_script.nil?
|
|
@@ -200,27 +187,7 @@ module Aspera
|
|
|
200
187
|
RestParameters.instance.send(method, v)
|
|
201
188
|
elsif k.eql?('ssl_options')
|
|
202
189
|
keys_to_delete.push(k)
|
|
203
|
-
|
|
204
|
-
Aspera.assert_type(v, Array){'ssl_options'}
|
|
205
|
-
# Start with default options
|
|
206
|
-
ssl_options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options]
|
|
207
|
-
v.each do |opt|
|
|
208
|
-
case opt
|
|
209
|
-
when Integer
|
|
210
|
-
ssl_options = opt
|
|
211
|
-
when String
|
|
212
|
-
name = "OP_#{opt.start_with?('-') ? opt[1..] : opt}".upcase
|
|
213
|
-
raise Cli::BadArgument, "Unknown 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)
|
|
214
|
-
if opt.start_with?('-')
|
|
215
|
-
ssl_options &= ~OpenSSL::SSL.const_get(name)
|
|
216
|
-
else
|
|
217
|
-
ssl_options |= OpenSSL::SSL.const_get(name)
|
|
218
|
-
end
|
|
219
|
-
else
|
|
220
|
-
Aspera.error_unexpected_value(opt.class.name){'Expected String or Integer in ssl_options'}
|
|
221
|
-
end
|
|
222
|
-
end
|
|
223
|
-
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options] = ssl_options
|
|
190
|
+
Aspera::SSL.option_list = v
|
|
224
191
|
elsif OAuth::Factory.instance.parameters.key?(k.to_sym)
|
|
225
192
|
keys_to_delete.push(k)
|
|
226
193
|
OAuth::Factory.instance.parameters[k.to_sym] = v
|
|
@@ -238,11 +205,31 @@ module Aspera
|
|
|
238
205
|
attr_accessor :main_folder, :option_cache_tokens, :option_insecure, :option_warn_insecure_cert, :option_http_options
|
|
239
206
|
attr_reader :option_ignore_cert_host_port, :progress_bar
|
|
240
207
|
|
|
208
|
+
def set_sdk_dir
|
|
209
|
+
# Check SDK folder is set or not, for compatibility, we check in two places
|
|
210
|
+
sdk_dir = Products::Transferd.sdk_directory rescue nil
|
|
211
|
+
if sdk_dir.nil?
|
|
212
|
+
@sdk_default_location = true
|
|
213
|
+
Log.log.debug('SDK folder is not set, checking default')
|
|
214
|
+
# New location
|
|
215
|
+
sdk_dir = self.class.default_app_main_folder(app_name: TRANSFERD_APP_NAME)
|
|
216
|
+
Log.log.debug{"Checking: #{sdk_dir}"}
|
|
217
|
+
if !Dir.exist?(sdk_dir)
|
|
218
|
+
Log.log.debug{"No such folder: #{sdk_dir}"}
|
|
219
|
+
# Former location
|
|
220
|
+
former_sdk_folder = File.join(self.class.default_app_main_folder(app_name: Info::CMD_NAME), TRANSFERD_APP_NAME)
|
|
221
|
+
Log.log.debug{"Checking: #{former_sdk_folder}"}
|
|
222
|
+
sdk_dir = former_sdk_folder if Dir.exist?(former_sdk_folder)
|
|
223
|
+
end
|
|
224
|
+
Log.log.debug{"Using: #{sdk_dir}"}
|
|
225
|
+
Products::Transferd.sdk_directory = sdk_dir
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
241
229
|
# Add files, folders or default locations to the certificate store
|
|
242
|
-
# @param path_list [Array<String>]
|
|
230
|
+
# @param path_list [Array<String>] List of paths to add
|
|
243
231
|
# @return the list of paths
|
|
244
232
|
def trusted_cert_locations=(path_list)
|
|
245
|
-
path_list = [path_list] unless path_list.is_a?(Array)
|
|
246
233
|
Aspera.assert_type(path_list, Array){'cert locations'}
|
|
247
234
|
if @certificate_store.nil?
|
|
248
235
|
Log.log.debug('Creating SSL Cert store')
|
|
@@ -273,6 +260,7 @@ module Aspera
|
|
|
273
260
|
pp = Dir.entries(p)
|
|
274
261
|
.map{ |e| File.realpath(File.join(p, e))}
|
|
275
262
|
.select{ |entry| File.file?(entry)}
|
|
263
|
+
.select{ |entry| CERT_EXT.any?{ |ext| entry.end_with?(ext)}}
|
|
276
264
|
end
|
|
277
265
|
@certificate_paths.concat(pp)
|
|
278
266
|
end
|
|
@@ -285,7 +273,7 @@ module Aspera
|
|
|
285
273
|
locations = @certificate_paths
|
|
286
274
|
if locations.nil?
|
|
287
275
|
# Compute default locations
|
|
288
|
-
self.trusted_cert_locations = SpecialValues::DEF
|
|
276
|
+
self.trusted_cert_locations = [SpecialValues::DEF]
|
|
289
277
|
locations = @certificate_paths
|
|
290
278
|
# Restore defaults
|
|
291
279
|
@certificate_paths = @certificate_store = nil
|
|
@@ -447,7 +435,7 @@ module Aspera
|
|
|
447
435
|
Log.log.warn{"keeping same value for #{preset}: #{param_name}: #{param_value}"}
|
|
448
436
|
return
|
|
449
437
|
end
|
|
450
|
-
Log.log.warn{"overwriting value: #{selected_preset[param_name]}"}
|
|
438
|
+
Log.log.warn{"overwriting value for #{param_name}: #{selected_preset[param_name]}"}
|
|
451
439
|
end
|
|
452
440
|
selected_preset[param_name] = param_value
|
|
453
441
|
formatter.display_status("Updated: #{preset}: #{param_name} <- #{param_value}")
|
|
@@ -479,21 +467,12 @@ module Aspera
|
|
|
479
467
|
raise Cli::Error, "Unknown config preset: #{include_path}" if current.nil?
|
|
480
468
|
end
|
|
481
469
|
current = self.class.deep_clone(current) unless current.is_a?(String)
|
|
482
|
-
return ExtendedValue.instance.evaluate(current)
|
|
483
|
-
end
|
|
484
|
-
|
|
485
|
-
def option_use_product=(value)
|
|
486
|
-
Ascp::Installation.instance.use_ascp_from_product(value)
|
|
487
|
-
end
|
|
488
|
-
|
|
489
|
-
def option_use_product
|
|
490
|
-
'write-only option, see value of ascp_path'
|
|
470
|
+
return ExtendedValue.instance.evaluate(current, context: 'preset')
|
|
491
471
|
end
|
|
492
472
|
|
|
493
473
|
def option_plugin_folder=(value)
|
|
494
|
-
|
|
495
|
-
value
|
|
496
|
-
Aspera.assert(value.all?(String)){'plugin folder'}
|
|
474
|
+
value = [value] unless value.is_a?(Array)
|
|
475
|
+
Aspera.assert_array_all(value, String){'plugin folder(s)'}
|
|
497
476
|
value.each{ |f| Plugins::Factory.instance.add_lookup_folder(f)}
|
|
498
477
|
end
|
|
499
478
|
|
|
@@ -624,7 +603,7 @@ module Aspera
|
|
|
624
603
|
# Collect info from ascp executable
|
|
625
604
|
data = Ascp::Installation.instance.ascp_info
|
|
626
605
|
# Add command line transfer spec
|
|
627
|
-
data['ts'] = transfer.
|
|
606
|
+
data['ts'] = transfer.user_transfer_spec
|
|
628
607
|
# Add keys
|
|
629
608
|
DataRepository::ELEMENTS.each_with_object(data){ |i, h| h[i.to_s] = DataRepository.instance.item(i)}
|
|
630
609
|
# Declare those as secrets
|
|
@@ -638,7 +617,7 @@ module Aspera
|
|
|
638
617
|
when :use
|
|
639
618
|
default_product = options.get_next_argument('product name')
|
|
640
619
|
Ascp::Installation.instance.use_ascp_from_product(default_product)
|
|
641
|
-
set_global_default(:ascp_path, Ascp::Installation
|
|
620
|
+
set_global_default(:ascp_path, "#{Ascp::Installation::USE_PRODUCT_PREFIX}#{default_product}")
|
|
642
621
|
return Main.result_nothing
|
|
643
622
|
end
|
|
644
623
|
when :install
|
|
@@ -725,7 +704,7 @@ module Aspera
|
|
|
725
704
|
value = @config_presets[name][param_name]
|
|
726
705
|
raise "no such option in preset #{name} : #{param_name}" if value.nil?
|
|
727
706
|
case value
|
|
728
|
-
when Numeric, String then return Main.result_text(ExtendedValue.instance.evaluate(value.to_s))
|
|
707
|
+
when Numeric, String then return Main.result_text(ExtendedValue.instance.evaluate(value.to_s, context: 'preset'))
|
|
729
708
|
end
|
|
730
709
|
return Main.result_single_object(value)
|
|
731
710
|
when :unset
|
|
@@ -754,7 +733,7 @@ module Aspera
|
|
|
754
733
|
options.ask_missing_mandatory = true
|
|
755
734
|
@config_presets[name] ||= {}
|
|
756
735
|
options.get_next_argument('option names', multiple: true).each do |option_name|
|
|
757
|
-
option_value = options.get_interactive(option_name,
|
|
736
|
+
option_value = options.get_interactive(option_name, check_option: true)
|
|
758
737
|
@config_presets[name][option_name] = option_value
|
|
759
738
|
end
|
|
760
739
|
return Main.result_status("Updated: #{name}")
|
|
@@ -889,7 +868,7 @@ module Aspera
|
|
|
889
868
|
result.push({
|
|
890
869
|
plugin: name,
|
|
891
870
|
detect: Formatter.tick(plugin_class.respond_to?(:detect)),
|
|
892
|
-
wizard: Formatter.tick(plugin_class.
|
|
871
|
+
wizard: Formatter.tick(plugin_class.method_defined?(:wizard)),
|
|
893
872
|
path: Plugins::Factory.instance.plugin_source(name)
|
|
894
873
|
})
|
|
895
874
|
end
|
|
@@ -930,10 +909,14 @@ module Aspera
|
|
|
930
909
|
when :ascp
|
|
931
910
|
execute_action_ascp
|
|
932
911
|
when :sync
|
|
933
|
-
case options.get_next_command(%i[spec])
|
|
912
|
+
case options.get_next_command(%i[spec admin translate])
|
|
934
913
|
when :spec
|
|
935
914
|
fields, data = Transfer::SpecDoc.man_table(Formatter, include_option: true, agent_columns: false, schema: Sync::Operations::CONF_SCHEMA)
|
|
936
915
|
return Main.result_object_list(data, fields: fields.map(&:to_s))
|
|
916
|
+
when :admin
|
|
917
|
+
return execute_sync_admin
|
|
918
|
+
when :translate
|
|
919
|
+
return Main.result_single_object(Sync::Operations.args_to_conf(options.get_next_argument('async arguments', multiple: true)))
|
|
937
920
|
else Aspera.error_unreachable_line
|
|
938
921
|
end
|
|
939
922
|
when :transferd
|
|
@@ -1227,6 +1210,7 @@ module Aspera
|
|
|
1227
1210
|
# Special extended values
|
|
1228
1211
|
EXTEND_PRESET = :preset
|
|
1229
1212
|
EXTEND_VAULT = :vault
|
|
1213
|
+
EXTEND_ARGS = :''
|
|
1230
1214
|
PRESET_DIG_SEPARATOR = '.'
|
|
1231
1215
|
DEFAULT_CHECK_NEW_VERSION_DAYS = 7
|
|
1232
1216
|
COFFEE_IMAGE_URL = 'https://enjoyjava.com/wp-content/uploads/2018/01/How-to-make-strong-coffee.jpg'
|
|
@@ -1235,7 +1219,7 @@ module Aspera
|
|
|
1235
1219
|
SELF_SIGNED_CERT = OpenSSL::SSL.const_get(:enon_yfirev.to_s.upcase.reverse) # cspell: disable-line
|
|
1236
1220
|
CONF_OVERVIEW_KEYS = %w[preset parameter value].freeze
|
|
1237
1221
|
SMTP_CONF_PARAMS = %i[server tls ssl port domain username password from_name from_email].freeze
|
|
1238
|
-
|
|
1222
|
+
CERT_EXT = %w[crt cer pem der].freeze
|
|
1239
1223
|
private_constant :ASPERA_HOME_FOLDER_NAME,
|
|
1240
1224
|
:DEFAULT_CONFIG_FILENAME,
|
|
1241
1225
|
:CONF_PRESET_CONFIG,
|
|
@@ -1260,7 +1244,8 @@ module Aspera
|
|
|
1260
1244
|
:TRANSFERD_APP_NAME,
|
|
1261
1245
|
:GLOBAL_DEFAULT_KEYWORD,
|
|
1262
1246
|
:CONF_GLOBAL_SYM,
|
|
1263
|
-
:GEM_CHECK_DATE_FMT
|
|
1247
|
+
:GEM_CHECK_DATE_FMT,
|
|
1248
|
+
:CERT_EXT
|
|
1264
1249
|
end
|
|
1265
1250
|
end
|
|
1266
1251
|
end
|
|
@@ -22,17 +22,18 @@ module Aspera
|
|
|
22
22
|
next unless base_url.start_with?('https://')
|
|
23
23
|
api = Rest.new(base_url: base_url, redirect_max: 2)
|
|
24
24
|
test_endpoint = 'login'
|
|
25
|
-
|
|
25
|
+
http = api.call(
|
|
26
26
|
operation: 'GET',
|
|
27
27
|
subpath: test_endpoint,
|
|
28
|
-
query: {local: true}
|
|
28
|
+
query: {local: true},
|
|
29
|
+
ret: :resp
|
|
29
30
|
)
|
|
30
|
-
next unless
|
|
31
|
+
next unless http.body.include?('Aspera Console')
|
|
31
32
|
version = 'unknown'
|
|
32
|
-
if (m =
|
|
33
|
+
if (m = http.body.match(/\(v([1-9]\..*)\)/))
|
|
33
34
|
version = m[1]
|
|
34
35
|
end
|
|
35
|
-
url =
|
|
36
|
+
url = http.uri.to_s
|
|
36
37
|
return {
|
|
37
38
|
version: version,
|
|
38
39
|
url: url[0..url.index(test_endpoint) - 2]
|
|
@@ -44,6 +45,10 @@ module Aspera
|
|
|
44
45
|
raise error if error
|
|
45
46
|
return
|
|
46
47
|
end
|
|
48
|
+
|
|
49
|
+
def time_to_string(time)
|
|
50
|
+
return time.strftime('%Y-%m-%d %H:%M:%S')
|
|
51
|
+
end
|
|
47
52
|
end
|
|
48
53
|
|
|
49
54
|
# @param wizard [Wizard] The wizard object
|
|
@@ -91,7 +96,7 @@ module Aspera
|
|
|
91
96
|
rescue StandardError => e
|
|
92
97
|
nagios.add_critical('console api', e.to_s)
|
|
93
98
|
end
|
|
94
|
-
|
|
99
|
+
Main.result_object_list(nagios.status_list)
|
|
95
100
|
when :transfer
|
|
96
101
|
command = options.get_next_command(%i[current smart])
|
|
97
102
|
case command
|
|
@@ -113,8 +118,8 @@ module Aspera
|
|
|
113
118
|
query = query_read_delete(default: {})
|
|
114
119
|
if query['from'].nil? && query['to'].nil?
|
|
115
120
|
time_now = Time.now
|
|
116
|
-
query['from'] =
|
|
117
|
-
query['to'] =
|
|
121
|
+
query['from'] = self.class.time_to_string(time_now - DEFAULT_FILTER_AGE_SECONDS)
|
|
122
|
+
query['to'] = self.class.time_to_string(time_now)
|
|
118
123
|
end
|
|
119
124
|
if (filter = query.delete('filter'))
|
|
120
125
|
parse_extended_filter(filter, query)
|
|
@@ -15,7 +15,7 @@ module Aspera
|
|
|
15
15
|
options.declare(:endpoint, 'Storage endpoint (URL)')
|
|
16
16
|
options.declare(:apikey, 'Storage API key')
|
|
17
17
|
options.declare(:crn, 'Resource instance id (CRN)')
|
|
18
|
-
options.declare(:service_credentials, 'IBM Cloud service credentials',
|
|
18
|
+
options.declare(:service_credentials, 'IBM Cloud service credentials', allowed: [Hash, NilClass])
|
|
19
19
|
options.declare(:region, 'Storage region')
|
|
20
20
|
options.declare(:identity, "Authentication URL (#{Api::CosNode::IBM_CLOUD_TOKEN_URL})", default: Api::CosNode::IBM_CLOUD_TOKEN_URL)
|
|
21
21
|
options.parse_options!
|
|
@@ -47,22 +47,23 @@ module Aspera
|
|
|
47
47
|
urls.each do |base_url|
|
|
48
48
|
next unless base_url.start_with?('https://')
|
|
49
49
|
api = Rest.new(base_url: base_url, redirect_max: 1)
|
|
50
|
-
|
|
50
|
+
http = api.call(
|
|
51
51
|
operation: 'POST',
|
|
52
52
|
headers: {
|
|
53
53
|
'Content-type' => Rest::MIME_TEXT,
|
|
54
54
|
'Accept' => 'application/xrds+xml'
|
|
55
|
-
}
|
|
55
|
+
},
|
|
56
|
+
ret: :resp
|
|
56
57
|
)
|
|
57
58
|
# 4.x
|
|
58
|
-
next unless
|
|
59
|
-
res_s = XmlSimple.xml_in(
|
|
60
|
-
Log.log.debug{"version: #{
|
|
59
|
+
next unless http.body.start_with?('<?xml')
|
|
60
|
+
res_s = XmlSimple.xml_in(http.body, {'ForceArray' => false})
|
|
61
|
+
Log.log.debug{"version: #{http[HEADER_FASPEX_VERSION]}"}
|
|
61
62
|
version = res_s['XRD']['application']['version']
|
|
62
63
|
# take redirect if any
|
|
63
64
|
return {
|
|
64
65
|
version: version,
|
|
65
|
-
url:
|
|
66
|
+
url: http.uri.to_s
|
|
66
67
|
}
|
|
67
68
|
rescue StandardError => e
|
|
68
69
|
error = e
|
|
@@ -125,11 +126,11 @@ module Aspera
|
|
|
125
126
|
@api_v3 = nil
|
|
126
127
|
@api_v4 = nil
|
|
127
128
|
options.declare(:link, 'Public link for specific operation')
|
|
128
|
-
options.declare(:delivery_info, 'Package delivery information',
|
|
129
|
+
options.declare(:delivery_info, 'Package delivery information', allowed: Hash)
|
|
129
130
|
options.declare(:remote_source, 'Remote source for package send (id or %name:)')
|
|
130
131
|
options.declare(:storage, 'Faspex local storage definition (for browsing source)')
|
|
131
132
|
options.declare(:recipient, 'Use if recipient is a dropbox (with *)')
|
|
132
|
-
options.declare(:box, 'Package box',
|
|
133
|
+
options.declare(:box, 'Package box', allowed: ATOM_MAILBOXES, default: :inbox)
|
|
133
134
|
options.parse_options!
|
|
134
135
|
end
|
|
135
136
|
|
|
@@ -184,8 +185,9 @@ module Aspera
|
|
|
184
185
|
operation: 'GET',
|
|
185
186
|
subpath: "#{mailbox}.atom",
|
|
186
187
|
headers: {'Accept' => 'application/xml'},
|
|
187
|
-
query: mailbox_query
|
|
188
|
-
|
|
188
|
+
query: mailbox_query,
|
|
189
|
+
ret: :resp
|
|
190
|
+
).body
|
|
189
191
|
box_data = XmlSimple.xml_in(atom_xml, {'ForceArray' => %w[entry field link to]})
|
|
190
192
|
Log.dump(:box_data, box_data)
|
|
191
193
|
items = box_data.key?('entry') ? box_data['entry'] : []
|
|
@@ -251,8 +253,9 @@ module Aspera
|
|
|
251
253
|
subpath: create_path,
|
|
252
254
|
content_type: Rest::MIME_JSON,
|
|
253
255
|
body: package_create_params,
|
|
254
|
-
headers: {'Accept' => 'text/javascript'}
|
|
255
|
-
|
|
256
|
+
headers: {'Accept' => 'text/javascript'},
|
|
257
|
+
ret: :resp
|
|
258
|
+
).body
|
|
256
259
|
# get arguments of function call
|
|
257
260
|
package_creation_data.delete!("\n") # one line
|
|
258
261
|
package_creation_data.gsub!(/^[^"]+\("\{/, '{') # delete header
|
|
@@ -280,7 +283,7 @@ module Aspera
|
|
|
280
283
|
rescue StandardError => e
|
|
281
284
|
nagios.add_critical('faspex api', e.to_s)
|
|
282
285
|
end
|
|
283
|
-
|
|
286
|
+
Main.result_object_list(nagios.status_list)
|
|
284
287
|
when :package
|
|
285
288
|
command_pkg = options.get_next_command(%i[send receive list show], aliases: {recv: :receive})
|
|
286
289
|
case command_pkg
|
|
@@ -300,10 +303,11 @@ module Aspera
|
|
|
300
303
|
delivery_info['sources'] ||= [{'paths' => []}]
|
|
301
304
|
first_source = delivery_info['sources'].first
|
|
302
305
|
first_source['paths'].concat(transfer.source_list)
|
|
303
|
-
source_id =
|
|
304
|
-
|
|
306
|
+
source_id = options.get_option(:remote_source)
|
|
307
|
+
if source_id && (m = Base.percent_selector(source_id))
|
|
308
|
+
Aspera.assert(m[:field].eql?('name'), type: Cli::BadArgument){'only name as selector, or give id'}
|
|
305
309
|
source_list = api_v3.read('source_shares')['items']
|
|
306
|
-
self.class.get_source_id_by_name(value, source_list)
|
|
310
|
+
source_id = self.class.get_source_id_by_name(m[:value], source_list)
|
|
307
311
|
end
|
|
308
312
|
first_source['id'] = source_id.to_i unless source_id.nil?
|
|
309
313
|
pkg_created = api_v3.create('send', package_create_params)
|
|
@@ -362,7 +366,7 @@ module Aspera
|
|
|
362
366
|
when :inbox, :archive then'received'
|
|
363
367
|
when :sent then 'sent'
|
|
364
368
|
end
|
|
365
|
-
entry_xml = api_v3.call(operation: 'GET', subpath: "#{endpoint}/#{delivery_id}", headers: {'Accept' => 'application/xml'})
|
|
369
|
+
entry_xml = api_v3.call(operation: 'GET', subpath: "#{endpoint}/#{delivery_id}", headers: {'Accept' => 'application/xml'}, ret: :resp).body
|
|
366
370
|
package_entry = XmlSimple.xml_in(entry_xml, {'ForceArray' => true})
|
|
367
371
|
pkg_id_uri = [{id: delivery_id, uri: self.class.get_fasp_uri_from_entry(package_entry)}]
|
|
368
372
|
end
|
|
@@ -373,17 +377,18 @@ module Aspera
|
|
|
373
377
|
raise Cli::BadArgument, "Pub link is #{link_data[:subpath]}. Expecting #{PUB_LINK_EXTERNAL_MATCH}" if !link_data[:subpath].start_with?(PUB_LINK_EXTERNAL_MATCH)
|
|
374
378
|
# NOTE: unauthenticated API (authorization is in url params)
|
|
375
379
|
api_public_link = Rest.new(base_url: link_data[:base_url])
|
|
376
|
-
|
|
380
|
+
pkg_xml = api_public_link.call(
|
|
377
381
|
operation: 'GET',
|
|
378
382
|
subpath: link_data[:subpath],
|
|
379
383
|
headers: {'Accept' => 'application/xml'},
|
|
380
|
-
query: {passcode: link_data[:query]['passcode']}
|
|
381
|
-
|
|
382
|
-
|
|
384
|
+
query: {passcode: link_data[:query]['passcode']},
|
|
385
|
+
ret: :resp
|
|
386
|
+
).body
|
|
387
|
+
if !pkg_xml.start_with?('<?xml ')
|
|
383
388
|
Environment.instance.open_uri(link_url)
|
|
384
389
|
raise Cli::Error, 'Unexpected response: package not found ?'
|
|
385
390
|
end
|
|
386
|
-
package_entry = XmlSimple.xml_in(
|
|
391
|
+
package_entry = XmlSimple.xml_in(pkg_xml, {'ForceArray' => false})
|
|
387
392
|
Log.dump(:package_entry, package_entry)
|
|
388
393
|
transfer_uri = self.class.get_fasp_uri_from_entry(package_entry)
|
|
389
394
|
pkg_id_uri = [{id: package_entry['id'], uri: transfer_uri}]
|
|
@@ -412,8 +417,9 @@ module Aspera
|
|
|
412
417
|
query: {'direction' => 'down'},
|
|
413
418
|
content_type: Rest::MIME_TEXT,
|
|
414
419
|
body: xml_payload,
|
|
415
|
-
headers: {'Accept' => Rest::MIME_TEXT, 'Content-Type' => 'application/vnd.aspera.url-list+xml'}
|
|
416
|
-
|
|
420
|
+
headers: {'Accept' => Rest::MIME_TEXT, 'Content-Type' => 'application/vnd.aspera.url-list+xml'},
|
|
421
|
+
ret: :resp
|
|
422
|
+
).body
|
|
417
423
|
end
|
|
418
424
|
transfer_spec['direction'] = Transfer::Spec::DIRECTION_RECEIVE
|
|
419
425
|
statuses = transfer.start(transfer_spec)
|
|
@@ -455,7 +461,7 @@ module Aspera
|
|
|
455
461
|
when :info
|
|
456
462
|
return Main.result_single_object(source_info)
|
|
457
463
|
when :node
|
|
458
|
-
node_config = ExtendedValue.instance.evaluate(source_info[KEY_NODE])
|
|
464
|
+
node_config = ExtendedValue.instance.evaluate(source_info[KEY_NODE], context: 'faspex node')
|
|
459
465
|
Log.log.debug{"node=#{node_config}"}
|
|
460
466
|
Aspera.assert_type(node_config, Hash, type: Cli::Error){source_info[KEY_NODE]}
|
|
461
467
|
api_node = Rest.new(
|
|
@@ -519,7 +525,7 @@ module Aspera
|
|
|
519
525
|
end
|
|
520
526
|
return Main.result_object_list(users)
|
|
521
527
|
when :login_methods
|
|
522
|
-
login_meths = api_v3.call(operation: 'GET', subpath: 'login/new', headers: {'Accept' => 'application/xrds+xml'})
|
|
528
|
+
login_meths = api_v3.call(operation: 'GET', subpath: 'login/new', headers: {'Accept' => 'application/xrds+xml'}, ret: :resp).body
|
|
523
529
|
login_methods = XmlSimple.xml_in(login_meths, {'ForceArray' => false})
|
|
524
530
|
return Main.result_object_list(login_methods['XRD']['Service'])
|
|
525
531
|
end
|