aspera-cli 4.17.0 → 4.18.1
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 +3 -4
- data/CHANGELOG.md +33 -0
- data/CONTRIBUTING.md +15 -1
- data/README.md +711 -432
- data/bin/ascli +5 -0
- data/bin/asession +2 -2
- data/examples/build_package.sh +28 -0
- data/lib/aspera/agent/alpha.rb +10 -8
- data/lib/aspera/agent/base.rb +9 -6
- data/lib/aspera/agent/connect.rb +7 -8
- data/lib/aspera/agent/direct.rb +56 -37
- data/lib/aspera/agent/httpgw.rb +23 -324
- data/lib/aspera/agent/node.rb +19 -20
- data/lib/aspera/agent/trsdk.rb +19 -20
- data/lib/aspera/api/aoc.rb +17 -14
- data/lib/aspera/api/cos_node.rb +4 -4
- data/lib/aspera/api/httpgw.rb +342 -0
- data/lib/aspera/api/node.rb +135 -89
- data/lib/aspera/ascmd.rb +4 -3
- data/lib/aspera/ascp/installation.rb +15 -7
- data/lib/aspera/ascp/management.rb +2 -2
- data/lib/aspera/ascp/products.rb +1 -1
- data/lib/aspera/cli/basic_auth_plugin.rb +5 -9
- data/lib/aspera/cli/extended_value.rb +35 -16
- data/lib/aspera/cli/formatter.rb +161 -70
- data/lib/aspera/cli/hints.rb +18 -0
- data/lib/aspera/cli/main.rb +32 -39
- data/lib/aspera/cli/manager.rb +151 -119
- data/lib/aspera/cli/plugin.rb +27 -21
- data/lib/aspera/cli/plugin_factory.rb +31 -20
- data/lib/aspera/cli/plugins/alee.rb +14 -2
- data/lib/aspera/cli/plugins/aoc.rb +152 -141
- data/lib/aspera/cli/plugins/ats.rb +1 -1
- data/lib/aspera/cli/plugins/config.rb +72 -65
- data/lib/aspera/cli/plugins/console.rb +8 -5
- data/lib/aspera/cli/plugins/faspex.rb +32 -23
- data/lib/aspera/cli/plugins/faspex5.rb +232 -156
- data/lib/aspera/cli/plugins/faspio.rb +85 -0
- data/lib/aspera/cli/plugins/httpgw.rb +55 -0
- data/lib/aspera/cli/plugins/node.rb +129 -64
- data/lib/aspera/cli/plugins/orchestrator.rb +33 -30
- data/lib/aspera/cli/plugins/preview.rb +7 -3
- data/lib/aspera/cli/plugins/server.rb +6 -6
- data/lib/aspera/cli/plugins/shares.rb +16 -14
- data/lib/aspera/cli/special_values.rb +13 -0
- data/lib/aspera/cli/sync_actions.rb +10 -10
- data/lib/aspera/cli/transfer_agent.rb +7 -6
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/environment.rb +70 -9
- data/lib/aspera/faspex_gw.rb +5 -4
- data/lib/aspera/faspex_postproc.rb +2 -2
- data/lib/aspera/log.rb +6 -3
- data/lib/aspera/node_simulator.rb +2 -2
- data/lib/aspera/oauth/base.rb +31 -19
- data/lib/aspera/oauth/factory.rb +12 -13
- data/lib/aspera/oauth/generic.rb +1 -0
- data/lib/aspera/oauth/jwt.rb +18 -15
- data/lib/aspera/oauth/url_json.rb +8 -6
- data/lib/aspera/oauth/web.rb +2 -2
- data/lib/aspera/persistency_folder.rb +2 -2
- data/lib/aspera/preview/generator.rb +3 -3
- data/lib/aspera/preview/options.rb +3 -3
- data/lib/aspera/preview/terminal.rb +4 -4
- data/lib/aspera/preview/utils.rb +3 -3
- data/lib/aspera/proxy_auto_config.rb +5 -1
- data/lib/aspera/rest.rb +105 -88
- data/lib/aspera/rest_call_error.rb +1 -1
- data/lib/aspera/rest_error_analyzer.rb +2 -2
- data/lib/aspera/rest_errors_aspera.rb +1 -1
- data/lib/aspera/resumer.rb +1 -1
- data/lib/aspera/secret_hider.rb +2 -4
- data/lib/aspera/ssh.rb +1 -1
- data/lib/aspera/transfer/parameters.rb +39 -36
- data/lib/aspera/transfer/spec.rb +2 -0
- data/lib/aspera/transfer/sync.rb +2 -1
- data/lib/aspera/transfer/uri.rb +1 -1
- data/lib/aspera/uri_reader.rb +5 -4
- data/lib/aspera/web_auth.rb +1 -1
- data/lib/aspera/web_server_simple.rb +4 -3
- data.tar.gz.sig +0 -0
- metadata +7 -4
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/plugins/bss.rb +0 -71
- data/lib/aspera/open_application.rb +0 -71
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# cspell:ignore initdemo genkey pubkey asperasoft
|
|
3
|
+
# cspell:ignore initdemo genkey pubkey asperasoft filelists
|
|
4
4
|
require 'aspera/cli/basic_auth_plugin'
|
|
5
5
|
require 'aspera/cli/extended_value'
|
|
6
|
+
require 'aspera/cli/special_values'
|
|
6
7
|
require 'aspera/cli/version'
|
|
7
8
|
require 'aspera/cli/formatter'
|
|
8
9
|
require 'aspera/cli/info'
|
|
@@ -15,7 +16,7 @@ require 'aspera/transfer/spec'
|
|
|
15
16
|
require 'aspera/keychain/encrypted_hash'
|
|
16
17
|
require 'aspera/keychain/macos_security'
|
|
17
18
|
require 'aspera/proxy_auto_config'
|
|
18
|
-
require 'aspera/
|
|
19
|
+
require 'aspera/environment'
|
|
19
20
|
require 'aspera/persistency_action_once'
|
|
20
21
|
require 'aspera/id_generator'
|
|
21
22
|
require 'aspera/persistency_folder'
|
|
@@ -25,6 +26,7 @@ require 'aspera/rest'
|
|
|
25
26
|
require 'aspera/log'
|
|
26
27
|
require 'aspera/assert'
|
|
27
28
|
require 'aspera/oauth'
|
|
29
|
+
require 'openssl'
|
|
28
30
|
require 'open3'
|
|
29
31
|
require 'date'
|
|
30
32
|
require 'erb'
|
|
@@ -141,7 +143,7 @@ module Aspera
|
|
|
141
143
|
Aspera.assert(!app_name.empty?)
|
|
142
144
|
return File.join(module_family_folder, app_name)
|
|
143
145
|
end
|
|
144
|
-
end
|
|
146
|
+
end
|
|
145
147
|
|
|
146
148
|
def initialize(gem:, name:, help:, version:, **env)
|
|
147
149
|
# we need to defer parsing of options until we have the config file, so we can use @extend with @preset
|
|
@@ -163,7 +165,6 @@ module Aspera
|
|
|
163
165
|
@option_http_options = {}
|
|
164
166
|
@ssl_warned_urls = []
|
|
165
167
|
@option_cache_tokens = true
|
|
166
|
-
@proxy_credentials = nil
|
|
167
168
|
@main_folder = nil
|
|
168
169
|
@option_config_file = nil
|
|
169
170
|
# store is used for ruby https
|
|
@@ -230,9 +231,10 @@ module Aspera
|
|
|
230
231
|
options.declare(:silent_insecure, 'Issue a warning if certificate is ignored', values: :bool, handler: {o: self, m: :option_warn_insecure_cert}, default: :yes)
|
|
231
232
|
options.declare(:cert_stores, 'List of folder with trusted certificates', types: [Array, String], handler: {o: self, m: :trusted_cert_locations})
|
|
232
233
|
options.declare(:http_options, 'Options for HTTP/S socket', types: Hash, handler: {o: self, m: :option_http_options}, default: {})
|
|
234
|
+
options.declare(:http_proxy, 'URL for HTTP proxy with optional credentials', types: String, handler: {o: self, m: :option_http_proxy})
|
|
233
235
|
options.declare(:cache_tokens, 'Save and reuse OAuth tokens', values: :bool, handler: {o: self, m: :option_cache_tokens})
|
|
234
236
|
options.declare(:fpac, 'Proxy auto configuration script')
|
|
235
|
-
options.declare(:proxy_credentials, 'HTTP proxy credentials
|
|
237
|
+
options.declare(:proxy_credentials, 'HTTP proxy credentials for fpac. Array: user,password', types: Array)
|
|
236
238
|
options.parse_options!
|
|
237
239
|
@progress_bar = TransferProgress.new if options.get_option(:progress_bar)
|
|
238
240
|
# Check SDK folder is set or not, for compatibility, we check in two places
|
|
@@ -255,20 +257,21 @@ module Aspera
|
|
|
255
257
|
end
|
|
256
258
|
pac_script = options.get_option(:fpac)
|
|
257
259
|
# create PAC executor
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
260
|
+
if !pac_script.nil?
|
|
261
|
+
@pac_exec = ProxyAutoConfig.new(pac_script).register_uri_generic
|
|
262
|
+
proxy_user_pass = options.get_option(:proxy_credentials)
|
|
263
|
+
if !proxy_user_pass.nil?
|
|
264
|
+
Aspera.assert(proxy_user_pass.length.eql?(2), exception_class: Cli::BadArgument){"proxy_credentials shall have two elements (#{proxy_user_pass.length})"}
|
|
265
|
+
@pac_exec.proxy_user = proxy_user_pass[0]
|
|
266
|
+
@pac_exec.proxy_pass = proxy_user_pass[1]
|
|
267
|
+
end
|
|
265
268
|
end
|
|
266
269
|
Rest.set_parameters(
|
|
267
270
|
user_agent: PROGRAM_NAME,
|
|
268
271
|
session_cb: lambda{|http_session|update_http_session(http_session)},
|
|
269
272
|
progress_bar: @progress_bar)
|
|
270
273
|
OAuth::Factory.instance.persist_mgr = persistency if @option_cache_tokens
|
|
271
|
-
Transfer::Parameters.file_list_folder = File.join(@main_folder, 'filelists')
|
|
274
|
+
Transfer::Parameters.file_list_folder = File.join(@main_folder, 'filelists')
|
|
272
275
|
RestErrorAnalyzer.instance.log_file = File.join(@main_folder, 'rest_exceptions.log')
|
|
273
276
|
# register aspera REST call error handlers
|
|
274
277
|
RestErrorsAspera.register_handlers
|
|
@@ -291,7 +294,7 @@ module Aspera
|
|
|
291
294
|
Aspera.assert_type(path, String){'Expecting a String for certificate location'}
|
|
292
295
|
paths_to_add = [path]
|
|
293
296
|
Log.log.debug{"Adding cert location: #{path}"}
|
|
294
|
-
if path.eql?(
|
|
297
|
+
if path.eql?(SpecialValues::DEF)
|
|
295
298
|
@certificate_store.set_default_paths
|
|
296
299
|
paths_to_add = [
|
|
297
300
|
OpenSSL::X509::DEFAULT_CERT_DIR,
|
|
@@ -322,7 +325,7 @@ module Aspera
|
|
|
322
325
|
locations = @certificate_paths
|
|
323
326
|
if locations.nil?
|
|
324
327
|
# compute default locations
|
|
325
|
-
self.trusted_cert_locations =
|
|
328
|
+
self.trusted_cert_locations = SpecialValues::DEF
|
|
326
329
|
locations = @certificate_paths
|
|
327
330
|
# restore defaults
|
|
328
331
|
@certificate_paths = @certificate_store = nil
|
|
@@ -330,6 +333,15 @@ module Aspera
|
|
|
330
333
|
return locations
|
|
331
334
|
end
|
|
332
335
|
|
|
336
|
+
def option_http_proxy
|
|
337
|
+
return ENV['http_proxy']
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def option_http_proxy=(value)
|
|
341
|
+
URI.parse(value)
|
|
342
|
+
ENV['http_proxy'] = value
|
|
343
|
+
end
|
|
344
|
+
|
|
333
345
|
def option_ignore_cert_host_port=(url_list)
|
|
334
346
|
url_list.each do |url|
|
|
335
347
|
uri = URI.parse(url)
|
|
@@ -365,10 +377,6 @@ module Aspera
|
|
|
365
377
|
http_session.verify_mode = SELF_SIGNED_CERT if http_session.use_ssl? && ignore_cert?(http_session.address, http_session.port)
|
|
366
378
|
http_session.cert_store = @certificate_store if @certificate_store
|
|
367
379
|
Log.log.debug{"using cert store #{http_session.cert_store} (#{@certificate_store})"} unless http_session.cert_store.nil?
|
|
368
|
-
if @proxy_credentials
|
|
369
|
-
http_session.proxy_user = @proxy_credentials[:user]
|
|
370
|
-
http_session.proxy_pass = @proxy_credentials[:pass]
|
|
371
|
-
end
|
|
372
380
|
@option_http_options.each do |k, v|
|
|
373
381
|
method = "#{k}=".to_sym
|
|
374
382
|
# check if accessor is a method of Net::HTTP
|
|
@@ -453,7 +461,7 @@ module Aspera
|
|
|
453
461
|
def add_plugin_default_preset(plugin_name_sym)
|
|
454
462
|
default_config_name = get_plugin_default_config_name(plugin_name_sym)
|
|
455
463
|
Log.log.debug{"add_plugin_default_preset:#{plugin_name_sym}:#{default_config_name}"}
|
|
456
|
-
options.add_option_preset(preset_by_name(default_config_name),
|
|
464
|
+
options.add_option_preset(preset_by_name(default_config_name), 'default_plugin', override: false) unless default_config_name.nil?
|
|
457
465
|
return nil
|
|
458
466
|
end
|
|
459
467
|
|
|
@@ -539,12 +547,12 @@ module Aspera
|
|
|
539
547
|
|
|
540
548
|
def option_preset=(value)
|
|
541
549
|
case value
|
|
542
|
-
when String
|
|
543
|
-
options.add_option_preset(preset_by_name(value))
|
|
544
550
|
when Hash
|
|
545
|
-
options.add_option_preset(value)
|
|
551
|
+
options.add_option_preset(value, 'set')
|
|
552
|
+
when String
|
|
553
|
+
options.add_option_preset(preset_by_name(value), 'set_by_name')
|
|
546
554
|
else
|
|
547
|
-
raise 'Preset definition must be a String for name, or Hash for
|
|
555
|
+
raise 'Preset definition must be a String for preset name, or Hash for set of values'
|
|
548
556
|
end
|
|
549
557
|
end
|
|
550
558
|
|
|
@@ -613,18 +621,18 @@ module Aspera
|
|
|
613
621
|
check_only = check_only.to_sym unless check_only.nil?
|
|
614
622
|
found_apps = []
|
|
615
623
|
my_self_plugin_sym = self.class.name.split('::').last.downcase.to_sym
|
|
616
|
-
PluginFactory.instance.
|
|
624
|
+
PluginFactory.instance.plugin_list.each do |plugin_name_sym|
|
|
617
625
|
# no detection for internal plugin
|
|
618
626
|
next if plugin_name_sym.eql?(my_self_plugin_sym)
|
|
619
627
|
next if check_only && !check_only.eql?(plugin_name_sym)
|
|
620
628
|
# load plugin class
|
|
621
|
-
|
|
622
|
-
detect_plugin_class = PluginFactory.plugin_class(plugin_name_sym)
|
|
629
|
+
detect_plugin_class = PluginFactory.instance.plugin_class(plugin_name_sym)
|
|
623
630
|
# requires detection method
|
|
624
631
|
next unless detect_plugin_class.respond_to?(:detect)
|
|
625
632
|
detection_info = nil
|
|
626
633
|
begin
|
|
627
634
|
Log.log.debug{"detecting #{plugin_name_sym} at #{app_url}"}
|
|
635
|
+
formatter.long_operation_running("#{plugin_name_sym}\r")
|
|
628
636
|
detection_info = detect_plugin_class.detect(app_url)
|
|
629
637
|
rescue OpenSSL::SSL::SSLError => e
|
|
630
638
|
Log.log.warn(e.message)
|
|
@@ -639,7 +647,7 @@ module Aspera
|
|
|
639
647
|
app_name = detect_plugin_class.respond_to?(:application_name) ? detect_plugin_class.application_name : detect_plugin_class.name.split('::').last
|
|
640
648
|
# if there is a redirect, then the detector can override the url.
|
|
641
649
|
found_apps.push({product: plugin_name_sym, name: app_name, url: app_url, version: 'unknown'}.merge(detection_info))
|
|
642
|
-
end
|
|
650
|
+
end
|
|
643
651
|
raise "No known application found at #{app_url}" if found_apps.empty?
|
|
644
652
|
Aspera.assert(found_apps.all?{|a|a.keys.all?(Symbol)})
|
|
645
653
|
return found_apps
|
|
@@ -678,7 +686,7 @@ module Aspera
|
|
|
678
686
|
api_connect_cdn.call(operation: 'GET', subpath: file_url, save_to_file: File.join(folder_dest, filename))
|
|
679
687
|
return Main.result_status("Downloaded: #{filename}")
|
|
680
688
|
when :open
|
|
681
|
-
|
|
689
|
+
Environment.instance.open_uri(one_link['href'])
|
|
682
690
|
return Main.result_status("Opened: #{one_link['href']}")
|
|
683
691
|
end
|
|
684
692
|
end
|
|
@@ -726,7 +734,7 @@ module Aspera
|
|
|
726
734
|
when :spec
|
|
727
735
|
return {
|
|
728
736
|
type: :object_list,
|
|
729
|
-
data: Transfer::Parameters.man_table,
|
|
737
|
+
data: Transfer::Parameters.man_table(formatter),
|
|
730
738
|
fields: [%w[name type], Transfer::Parameters::SUPPORTED_AGENTS_SHORT.map(&:to_s), %w[description]].flatten.freeze
|
|
731
739
|
}
|
|
732
740
|
when :errors
|
|
@@ -779,11 +787,11 @@ module Aspera
|
|
|
779
787
|
when :set
|
|
780
788
|
param_name = options.get_next_argument('parameter name')
|
|
781
789
|
param_name = Manager.option_line_to_name(param_name)
|
|
782
|
-
param_value = options.get_next_argument('parameter value')
|
|
790
|
+
param_value = options.get_next_argument('parameter value', validation: nil)
|
|
783
791
|
set_preset_key(name, param_name, param_value)
|
|
784
792
|
return Main.result_nothing
|
|
785
793
|
when :initialize
|
|
786
|
-
config_value = options.get_next_argument('extended value',
|
|
794
|
+
config_value = options.get_next_argument('extended value', validation: Hash)
|
|
787
795
|
if @config_presets.key?(name)
|
|
788
796
|
Log.log.warn{"configuration already exists: #{name}, overwriting"}
|
|
789
797
|
end
|
|
@@ -791,16 +799,16 @@ module Aspera
|
|
|
791
799
|
return Main.result_status("Modified: #{@option_config_file}")
|
|
792
800
|
when :update
|
|
793
801
|
# get unprocessed options
|
|
794
|
-
unprocessed_options = options.
|
|
802
|
+
unprocessed_options = options.unprocessed_options_with_value
|
|
795
803
|
Log.log.debug{"opts=#{unprocessed_options}"}
|
|
796
804
|
@config_presets[name] ||= {}
|
|
797
805
|
@config_presets[name].merge!(unprocessed_options)
|
|
798
806
|
return Main.result_status("Updated: #{name}")
|
|
799
807
|
when :ask
|
|
800
|
-
options.ask_missing_mandatory =
|
|
808
|
+
options.ask_missing_mandatory = true
|
|
801
809
|
@config_presets[name] ||= {}
|
|
802
|
-
options.get_next_argument('option names',
|
|
803
|
-
option_value = options.get_interactive(
|
|
810
|
+
options.get_next_argument('option names', multiple: true).each do |option_name|
|
|
811
|
+
option_value = options.get_interactive(option_name, option: true)
|
|
804
812
|
@config_presets[name][option_name] = option_value
|
|
805
813
|
end
|
|
806
814
|
return Main.result_status("Updated: #{name}")
|
|
@@ -853,6 +861,7 @@ module Aspera
|
|
|
853
861
|
wizard
|
|
854
862
|
detect
|
|
855
863
|
coffee
|
|
864
|
+
image
|
|
856
865
|
ascp
|
|
857
866
|
email_test
|
|
858
867
|
smtp_settings
|
|
@@ -871,16 +880,16 @@ module Aspera
|
|
|
871
880
|
when :preset # newer syntax
|
|
872
881
|
return execute_preset
|
|
873
882
|
when :open
|
|
874
|
-
|
|
883
|
+
Environment.open_editor(@option_config_file.to_s)
|
|
875
884
|
return Main.result_nothing
|
|
876
885
|
when :documentation
|
|
877
886
|
section = options.get_next_argument('private key file path', mandatory: false)
|
|
878
887
|
section = "##{section}" unless section.nil?
|
|
879
|
-
|
|
888
|
+
Environment.instance.open_uri("#{@help}#{section}")
|
|
880
889
|
return Main.result_nothing
|
|
881
890
|
when :genkey # generate new rsa key
|
|
882
891
|
private_key_path = options.get_next_argument('private key file path')
|
|
883
|
-
private_key_length = options.get_next_argument('size in bits', mandatory: false,
|
|
892
|
+
private_key_length = options.get_next_argument('size in bits', mandatory: false, validation: Integer, default: DEFAULT_PRIV_KEY_LENGTH)
|
|
884
893
|
self.class.generate_rsa_private_key(path: private_key_path, length: private_key_length)
|
|
885
894
|
return Main.result_status("Generated #{private_key_length} bit RSA key: #{private_key_path}")
|
|
886
895
|
when :pubkey # get pub key
|
|
@@ -900,7 +909,7 @@ module Aspera
|
|
|
900
909
|
return Main.result_status(remote_chain.first.subject.to_a.find { |name, _, _| name == 'CN' }[1])
|
|
901
910
|
end
|
|
902
911
|
when :echo # display the content of a value given on command line
|
|
903
|
-
return Formatter.auto_type(options.get_next_argument('value'))
|
|
912
|
+
return Formatter.auto_type(options.get_next_argument('value', validation: nil))
|
|
904
913
|
when :flush_tokens
|
|
905
914
|
deleted_files = OAuth::Factory.instance.flush_tokens
|
|
906
915
|
return {type: :value_list, data: deleted_files, name: 'file'}
|
|
@@ -908,20 +917,19 @@ module Aspera
|
|
|
908
917
|
case options.get_next_command(%i[list create])
|
|
909
918
|
when :list
|
|
910
919
|
result = []
|
|
911
|
-
PluginFactory.instance.
|
|
912
|
-
|
|
913
|
-
plugin_klass = PluginFactory.plugin_class(name)
|
|
920
|
+
PluginFactory.instance.plugin_list.each do |name|
|
|
921
|
+
plugin_class = PluginFactory.instance.plugin_class(name)
|
|
914
922
|
result.push({
|
|
915
923
|
plugin: name,
|
|
916
|
-
detect: Formatter.tick(
|
|
917
|
-
wizard: Formatter.tick(
|
|
918
|
-
path:
|
|
924
|
+
detect: Formatter.tick(plugin_class.respond_to?(:detect)),
|
|
925
|
+
wizard: Formatter.tick(plugin_class.respond_to?(:wizard)),
|
|
926
|
+
path: PluginFactory.instance.plugin_source(name)
|
|
919
927
|
})
|
|
920
928
|
end
|
|
921
929
|
return {type: :object_list, data: result, fields: %w[plugin detect wizard path]}
|
|
922
930
|
when :create
|
|
923
|
-
plugin_name = options.get_next_argument('name'
|
|
924
|
-
destination_folder = options.get_next_argument('folder',
|
|
931
|
+
plugin_name = options.get_next_argument('name').downcase
|
|
932
|
+
destination_folder = options.get_next_argument('folder', mandatory: false) || File.join(@main_folder, ASPERA_PLUGINS_FOLDERNAME)
|
|
925
933
|
plugin_file = File.join(destination_folder, "#{plugin_name}.rb")
|
|
926
934
|
content = <<~END_OF_PLUGIN_CODE
|
|
927
935
|
require 'aspera/cli/plugin'
|
|
@@ -950,11 +958,9 @@ module Aspera
|
|
|
950
958
|
} if action.eql?(:detect)
|
|
951
959
|
return wizard_find(apps)
|
|
952
960
|
when :coffee
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
OpenApplication.instance.uri(COFFEE_IMAGE)
|
|
957
|
-
return Main.result_nothing
|
|
961
|
+
return Main.result_image(COFFEE_IMAGE, formatter: formatter)
|
|
962
|
+
when :image
|
|
963
|
+
return Main.result_image(options.get_next_argument('image uri or blob'), formatter: formatter)
|
|
958
964
|
when :ascp
|
|
959
965
|
execute_action_ascp
|
|
960
966
|
when :gem
|
|
@@ -1019,17 +1025,17 @@ module Aspera
|
|
|
1019
1025
|
apps.first
|
|
1020
1026
|
else
|
|
1021
1027
|
formatter.display_status('Multiple applications detected, please select from:')
|
|
1022
|
-
formatter.display_results(
|
|
1028
|
+
formatter.display_results(type: :object_list, data: apps, fields: %w[product url version])
|
|
1023
1029
|
answer = options.prompt_user_input_in_list('product', apps.map{|a|a[:product]})
|
|
1024
1030
|
apps.find{|a|a[:product].eql?(answer)}
|
|
1025
1031
|
end
|
|
1026
|
-
wiz_url = identification[:url]
|
|
1027
1032
|
Log.log.debug{Log.dump(:identification, identification)}
|
|
1033
|
+
wiz_url = identification[:url]
|
|
1028
1034
|
formatter.display_status("Using: #{identification[:name]} at #{wiz_url}".bold)
|
|
1029
1035
|
# set url for instantiation of plugin
|
|
1030
|
-
options.add_option_preset({url: wiz_url})
|
|
1036
|
+
options.add_option_preset({url: wiz_url}, 'wizard')
|
|
1031
1037
|
# instantiate plugin: command line options will be known and wizard can be called
|
|
1032
|
-
wiz_plugin_class = PluginFactory.plugin_class(identification[:product])
|
|
1038
|
+
wiz_plugin_class = PluginFactory.instance.plugin_class(identification[:product])
|
|
1033
1039
|
Aspera.assert(wiz_plugin_class.respond_to?(:wizard), exception_class: Cli::BadArgument) do
|
|
1034
1040
|
"Detected: #{identification[:product]}, but this application has no wizard"
|
|
1035
1041
|
end
|
|
@@ -1072,7 +1078,7 @@ module Aspera
|
|
|
1072
1078
|
Log.log.debug{"wizard result: #{wizard_result}"}
|
|
1073
1079
|
Aspera.assert(WIZARD_RESULT_KEYS.eql?(wizard_result.keys.sort)){"missing or extra keys in wizard result: #{wizard_result.keys}"}
|
|
1074
1080
|
# get preset name from user or default
|
|
1075
|
-
wiz_preset_name =
|
|
1081
|
+
wiz_preset_name = nil
|
|
1076
1082
|
if wiz_preset_name.nil?
|
|
1077
1083
|
elements = [
|
|
1078
1084
|
identification[:product],
|
|
@@ -1198,7 +1204,7 @@ module Aspera
|
|
|
1198
1204
|
return default_config_name
|
|
1199
1205
|
end
|
|
1200
1206
|
return nil
|
|
1201
|
-
end
|
|
1207
|
+
end
|
|
1202
1208
|
|
|
1203
1209
|
# TODO: delete: ALLOWED_KEYS = %i[password username description].freeze
|
|
1204
1210
|
# @return [Hash] result of execution of vault command
|
|
@@ -1208,19 +1214,20 @@ module Aspera
|
|
|
1208
1214
|
when :info
|
|
1209
1215
|
return {type: :single_object, data: vault_info}
|
|
1210
1216
|
when :list
|
|
1211
|
-
return {type: :object_list, data: vault.list}
|
|
1217
|
+
return {type: :object_list, data: vault.list, fields: %w(label url username password description)}
|
|
1212
1218
|
when :show
|
|
1213
1219
|
return {type: :single_object, data: vault.get(label: options.get_next_argument('label'))}
|
|
1214
1220
|
when :create
|
|
1215
|
-
label = options.get_next_argument('label',
|
|
1216
|
-
info = options.get_next_argument('info',
|
|
1221
|
+
label = options.get_next_argument('label', validation: String)
|
|
1222
|
+
info = options.get_next_argument('info', validation: Hash)
|
|
1217
1223
|
info = info.symbolize_keys
|
|
1218
1224
|
info[:label] = label
|
|
1219
1225
|
vault.set(info)
|
|
1220
1226
|
return Main.result_status('Password added')
|
|
1221
1227
|
when :delete
|
|
1222
|
-
|
|
1223
|
-
|
|
1228
|
+
label_to_delete = options.get_next_argument('label')
|
|
1229
|
+
vault.delete(label: label_to_delete)
|
|
1230
|
+
return Main.result_status("Entry deleted: #{label_to_delete}")
|
|
1224
1231
|
when :password
|
|
1225
1232
|
Aspera.assert(vault.respond_to?(:password=)){'Vault does not support password change'}
|
|
1226
1233
|
new_password = options.get_next_argument('new_password')
|
|
@@ -1264,7 +1271,7 @@ module Aspera
|
|
|
1264
1271
|
info[:password])
|
|
1265
1272
|
when 'system'
|
|
1266
1273
|
case Environment.os
|
|
1267
|
-
when Environment::
|
|
1274
|
+
when Environment::OS_MACOS
|
|
1268
1275
|
@vault = Keychain::MacosSystem.new(info[:name], info[:password])
|
|
1269
1276
|
else
|
|
1270
1277
|
raise 'not implemented for this OS'
|
|
@@ -18,7 +18,10 @@ module Aspera
|
|
|
18
18
|
next unless base_url.start_with?('https://')
|
|
19
19
|
api = Rest.new(base_url: base_url, redirect_max: 2)
|
|
20
20
|
test_endpoint = 'login'
|
|
21
|
-
test_page = api.call(
|
|
21
|
+
test_page = api.call(
|
|
22
|
+
operation: 'GET',
|
|
23
|
+
subpath: test_endpoint,
|
|
24
|
+
query: {local: true})
|
|
22
25
|
next unless test_page[:http].body.include?('Aspera Console')
|
|
23
26
|
version = 'unknown'
|
|
24
27
|
if (m = test_page[:http].body.match(/\(v([1-9]\..*)\)/))
|
|
@@ -102,7 +105,7 @@ module Aspera
|
|
|
102
105
|
end
|
|
103
106
|
end
|
|
104
107
|
end
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -5,11 +5,12 @@ require 'aspera/cli/basic_auth_plugin'
|
|
|
5
5
|
require 'aspera/cli/plugins/node'
|
|
6
6
|
require 'aspera/cli/plugins/config'
|
|
7
7
|
require 'aspera/cli/extended_value'
|
|
8
|
+
require 'aspera/cli/special_values'
|
|
8
9
|
require 'aspera/cli/transfer_agent'
|
|
9
10
|
require 'aspera/transfer/uri'
|
|
10
11
|
require 'aspera/transfer/spec'
|
|
11
12
|
require 'aspera/persistency_action_once'
|
|
12
|
-
require 'aspera/
|
|
13
|
+
require 'aspera/environment'
|
|
13
14
|
require 'aspera/nagios'
|
|
14
15
|
require 'aspera/id_generator'
|
|
15
16
|
require 'aspera/log'
|
|
@@ -179,7 +180,11 @@ module Aspera
|
|
|
179
180
|
loop do
|
|
180
181
|
# get a batch of package information
|
|
181
182
|
# order: first batch is latest packages, and then in a batch ids are increasing
|
|
182
|
-
atom_xml = api_v3.call(
|
|
183
|
+
atom_xml = api_v3.call(
|
|
184
|
+
operation: 'GET',
|
|
185
|
+
subpath: "#{mailbox}.atom",
|
|
186
|
+
headers: {'Accept' => 'application/xml'},
|
|
187
|
+
query: mailbox_query)[:http].body
|
|
183
188
|
box_data = XmlSimple.xml_in(atom_xml, {'ForceArray' => %w[entry field link to]})
|
|
184
189
|
Log.log.debug{Log.dump(:box_data, box_data)}
|
|
185
190
|
items = box_data.key?('entry') ? box_data['entry'] : []
|
|
@@ -246,8 +251,9 @@ module Aspera
|
|
|
246
251
|
package_creation_data = api_public_link.call(
|
|
247
252
|
operation: 'POST',
|
|
248
253
|
subpath: create_path,
|
|
249
|
-
|
|
250
|
-
|
|
254
|
+
headers: {'Accept' => 'text/javascript'},
|
|
255
|
+
body: package_create_params,
|
|
256
|
+
body_type: :json)[:http].body
|
|
251
257
|
# get arguments of function call
|
|
252
258
|
package_creation_data.delete!("\n") # one line
|
|
253
259
|
package_creation_data.gsub!(/^[^"]+\("\{/, '{') # delete header
|
|
@@ -308,8 +314,9 @@ module Aspera
|
|
|
308
314
|
pkg_created = api_v3.call(
|
|
309
315
|
operation: 'POST',
|
|
310
316
|
subpath: 'send',
|
|
311
|
-
|
|
312
|
-
|
|
317
|
+
headers: {'Accept' => 'application/json'},
|
|
318
|
+
body: package_create_params,
|
|
319
|
+
body_type: :json
|
|
313
320
|
)[:data]
|
|
314
321
|
if first_source.key?('id')
|
|
315
322
|
# no transfer spec if remote source: handled by faspex
|
|
@@ -347,9 +354,9 @@ module Aspera
|
|
|
347
354
|
delivery_id = instance_identifier
|
|
348
355
|
raise 'empty id' if delivery_id.empty?
|
|
349
356
|
recipient = options.get_option(:recipient)
|
|
350
|
-
if delivery_id.eql?(
|
|
357
|
+
if delivery_id.eql?(SpecialValues::ALL)
|
|
351
358
|
pkg_id_uri = mailbox_filtered_entries.map{|i|{id: i[PACKAGE_MATCH_FIELD], uri: self.class.get_fasp_uri_from_entry(i, raise_no_link: false)}}
|
|
352
|
-
elsif delivery_id.eql?(
|
|
359
|
+
elsif delivery_id.eql?(SpecialValues::INIT)
|
|
353
360
|
Aspera.assert(skip_ids_persistency){'Only with option once_only'}
|
|
354
361
|
skip_ids_persistency.data.clear.concat(mailbox_filtered_entries.map{|i|{id: i[PACKAGE_MATCH_FIELD]}})
|
|
355
362
|
skip_ids_persistency.save
|
|
@@ -380,18 +387,18 @@ module Aspera
|
|
|
380
387
|
api_public_link = Rest.new(base_url: link_data[:base_url])
|
|
381
388
|
package_creation_data = api_public_link.call(
|
|
382
389
|
operation: 'GET',
|
|
383
|
-
subpath:
|
|
384
|
-
|
|
385
|
-
|
|
390
|
+
subpath: link_data[:subpath],
|
|
391
|
+
headers: {'Accept' => 'application/xml'},
|
|
392
|
+
query: {passcode: link_data[:query]['passcode']})
|
|
386
393
|
if !package_creation_data[:http].body.start_with?('<?xml ')
|
|
387
|
-
|
|
394
|
+
Environment.instance.open_uri(link_url)
|
|
388
395
|
raise Cli::Error, 'Unexpected response: package not found ?'
|
|
389
396
|
end
|
|
390
397
|
package_entry = XmlSimple.xml_in(package_creation_data[:http].body, {'ForceArray' => false})
|
|
391
398
|
Log.log.debug{Log.dump(:package_entry, package_entry)}
|
|
392
399
|
transfer_uri = self.class.get_fasp_uri_from_entry(package_entry)
|
|
393
400
|
pkg_id_uri = [{id: package_entry['id'], uri: transfer_uri}]
|
|
394
|
-
end
|
|
401
|
+
end
|
|
395
402
|
# prune packages already downloaded
|
|
396
403
|
# TODO : remove ids from skip not present in inbox to avoid growing too big
|
|
397
404
|
# skip_ids_data.select!{|id|pkg_id_uri.select{|p|p[:id].eql?(id)}}
|
|
@@ -411,10 +418,12 @@ module Aspera
|
|
|
411
418
|
xml_payload =
|
|
412
419
|
%Q(<?xml version="1.0" encoding="UTF-8"?><url-list xmlns="http://schemas.asperasoft.com/xml/url-list"><url href="#{sanitized}"/></url-list>)
|
|
413
420
|
transfer_spec['token'] = api_v3.call(
|
|
414
|
-
operation:
|
|
415
|
-
subpath:
|
|
416
|
-
headers:
|
|
417
|
-
|
|
421
|
+
operation: 'POST',
|
|
422
|
+
subpath: 'issue-token',
|
|
423
|
+
headers: {'Accept' => 'text/plain', 'Content-Type' => 'application/vnd.aspera.url-list+xml'},
|
|
424
|
+
query: {'direction' => 'down'},
|
|
425
|
+
body: xml_payload,
|
|
426
|
+
body_type: :text)[:http].body
|
|
418
427
|
end
|
|
419
428
|
transfer_spec['direction'] = Transfer::Spec::DIRECTION_RECEIVE
|
|
420
429
|
statuses = transfer.start(transfer_spec)
|
|
@@ -502,9 +511,9 @@ module Aspera
|
|
|
502
511
|
when :address_book
|
|
503
512
|
result = api_v3.call(
|
|
504
513
|
operation: 'GET',
|
|
505
|
-
subpath:
|
|
506
|
-
headers:
|
|
507
|
-
|
|
514
|
+
subpath: 'address-book',
|
|
515
|
+
headers: {'Accept' => 'application/json'},
|
|
516
|
+
query: {'format' => 'json', 'count' => 100_000}
|
|
508
517
|
)[:data]
|
|
509
518
|
formatter.display_status("users: #{result['itemsPerPage']}/#{result['totalResults']}, start:#{result['startIndex']}")
|
|
510
519
|
users = result['entry']
|
|
@@ -526,9 +535,9 @@ module Aspera
|
|
|
526
535
|
login_meths = api_v3.call(operation: 'GET', subpath: 'login/new', headers: {'Accept' => 'application/xrds+xml'})[:http].body
|
|
527
536
|
login_methods = XmlSimple.xml_in(login_meths, {'ForceArray' => false})
|
|
528
537
|
return {type: :object_list, data: login_methods['XRD']['Service']}
|
|
529
|
-
end
|
|
538
|
+
end
|
|
530
539
|
end
|
|
531
540
|
end
|
|
532
541
|
end
|
|
533
|
-
end
|
|
534
|
-
end
|
|
542
|
+
end
|
|
543
|
+
end
|