aspera-cli 4.18.0 → 4.19.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 +23 -0
- data/CONTRIBUTING.md +5 -12
- data/README.md +152 -84
- data/examples/build_exec +85 -0
- data/examples/build_package.sh +28 -0
- data/lib/aspera/agent/alpha.rb +4 -4
- data/lib/aspera/agent/base.rb +2 -0
- data/lib/aspera/agent/connect.rb +3 -4
- data/lib/aspera/agent/direct.rb +108 -104
- data/lib/aspera/agent/httpgw.rb +1 -1
- data/lib/aspera/api/aoc.rb +2 -2
- data/lib/aspera/api/httpgw.rb +95 -57
- data/lib/aspera/api/node.rb +110 -77
- data/lib/aspera/ascp/installation.rb +47 -32
- data/lib/aspera/ascp/management.rb +4 -1
- data/lib/aspera/ascp/products.rb +2 -8
- data/lib/aspera/cli/extended_value.rb +27 -14
- data/lib/aspera/cli/formatter.rb +35 -28
- data/lib/aspera/cli/main.rb +11 -11
- data/lib/aspera/cli/manager.rb +109 -94
- data/lib/aspera/cli/plugin.rb +4 -7
- data/lib/aspera/cli/plugin_factory.rb +10 -1
- data/lib/aspera/cli/plugins/aoc.rb +15 -14
- data/lib/aspera/cli/plugins/config.rb +35 -29
- data/lib/aspera/cli/plugins/faspex.rb +5 -4
- data/lib/aspera/cli/plugins/faspex5.rb +16 -13
- data/lib/aspera/cli/plugins/node.rb +50 -41
- data/lib/aspera/cli/plugins/orchestrator.rb +3 -2
- data/lib/aspera/cli/plugins/preview.rb +1 -1
- data/lib/aspera/cli/plugins/server.rb +2 -2
- data/lib/aspera/cli/plugins/shares.rb +11 -7
- data/lib/aspera/cli/special_values.rb +13 -0
- data/lib/aspera/cli/sync_actions.rb +73 -32
- data/lib/aspera/cli/transfer_agent.rb +3 -2
- data/lib/aspera/cli/transfer_progress.rb +1 -1
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/environment.rb +100 -7
- data/lib/aspera/faspex_gw.rb +1 -1
- data/lib/aspera/keychain/encrypted_hash.rb +2 -0
- data/lib/aspera/log.rb +1 -0
- data/lib/aspera/node_simulator.rb +1 -1
- data/lib/aspera/oauth/jwt.rb +1 -1
- data/lib/aspera/oauth/url_json.rb +2 -0
- data/lib/aspera/oauth/web.rb +7 -6
- data/lib/aspera/rest.rb +46 -15
- data/lib/aspera/secret_hider.rb +3 -2
- data/lib/aspera/ssh.rb +1 -1
- data/lib/aspera/transfer/faux_file.rb +7 -5
- data/lib/aspera/transfer/parameters.rb +27 -19
- data/lib/aspera/transfer/spec.rb +8 -10
- data/lib/aspera/transfer/sync.rb +52 -47
- data/lib/aspera/web_auth.rb +0 -1
- data/lib/aspera/web_server_simple.rb +24 -13
- data.tar.gz.sig +0 -0
- metadata +5 -4
- metadata.gz.sig +0 -0
- data/examples/rubyc +0 -24
- data/lib/aspera/open_application.rb +0 -69
|
@@ -3,6 +3,7 @@
|
|
|
3
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'
|
|
@@ -280,6 +281,8 @@ module Aspera
|
|
|
280
281
|
attr_reader :option_ignore_cert_host_port, :progress_bar
|
|
281
282
|
|
|
282
283
|
# add files, folders or default locations to the certificate store
|
|
284
|
+
# @param path_list [Array<String>] list of paths to add
|
|
285
|
+
# @return the list of paths
|
|
283
286
|
def trusted_cert_locations=(path_list)
|
|
284
287
|
path_list = [path_list] unless path_list.is_a?(Array)
|
|
285
288
|
Aspera.assert_type(path_list, Array){'cert locations'}
|
|
@@ -293,12 +296,12 @@ module Aspera
|
|
|
293
296
|
Aspera.assert_type(path, String){'Expecting a String for certificate location'}
|
|
294
297
|
paths_to_add = [path]
|
|
295
298
|
Log.log.debug{"Adding cert location: #{path}"}
|
|
296
|
-
if path.eql?(
|
|
299
|
+
if path.eql?(SpecialValues::DEF)
|
|
297
300
|
@certificate_store.set_default_paths
|
|
298
|
-
paths_to_add = [
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
301
|
+
paths_to_add = [OpenSSL::X509::DEFAULT_CERT_DIR]
|
|
302
|
+
# JRuby cert file seems not to be PEM
|
|
303
|
+
paths_to_add.push(OpenSSL::X509::DEFAULT_CERT_FILE) unless defined?(JRUBY_VERSION)
|
|
304
|
+
paths_to_add.select!{|f|File.exist?(f)}
|
|
302
305
|
elsif File.file?(path)
|
|
303
306
|
@certificate_store.add_file(path)
|
|
304
307
|
elsif File.directory?(path)
|
|
@@ -324,7 +327,7 @@ module Aspera
|
|
|
324
327
|
locations = @certificate_paths
|
|
325
328
|
if locations.nil?
|
|
326
329
|
# compute default locations
|
|
327
|
-
self.trusted_cert_locations =
|
|
330
|
+
self.trusted_cert_locations = SpecialValues::DEF
|
|
328
331
|
locations = @certificate_paths
|
|
329
332
|
# restore defaults
|
|
330
333
|
@certificate_paths = @certificate_store = nil
|
|
@@ -577,7 +580,7 @@ module Aspera
|
|
|
577
580
|
@config_checksum_on_disk = config_checksum
|
|
578
581
|
end
|
|
579
582
|
files_to_copy = []
|
|
580
|
-
Log.log.
|
|
583
|
+
Log.log.trace1{Log.dump('Available_presets', @config_presets)}
|
|
581
584
|
Aspera.assert_type(@config_presets, Hash){'config file YAML'}
|
|
582
585
|
# check there is at least the config section
|
|
583
586
|
Aspera.assert(@config_presets.key?(CONF_PRESET_CONFIG)){"Cannot find key: #{CONF_PRESET_CONFIG}"}
|
|
@@ -685,7 +688,7 @@ module Aspera
|
|
|
685
688
|
api_connect_cdn.call(operation: 'GET', subpath: file_url, save_to_file: File.join(folder_dest, filename))
|
|
686
689
|
return Main.result_status("Downloaded: #{filename}")
|
|
687
690
|
when :open
|
|
688
|
-
|
|
691
|
+
Environment.instance.open_uri(one_link['href'])
|
|
689
692
|
return Main.result_status("Opened: #{one_link['href']}")
|
|
690
693
|
end
|
|
691
694
|
end
|
|
@@ -698,8 +701,7 @@ module Aspera
|
|
|
698
701
|
return execute_connect_action
|
|
699
702
|
when :use
|
|
700
703
|
ascp_path = options.get_next_argument('path to ascp')
|
|
701
|
-
|
|
702
|
-
formatter.display_status("ascp version: #{ascp_version}")
|
|
704
|
+
formatter.display_status("ascp version: #{Ascp::Installation.instance.get_ascp_version(ascp_path)}")
|
|
703
705
|
set_global_default(:ascp_path, ascp_path)
|
|
704
706
|
return Main.result_nothing
|
|
705
707
|
when :show
|
|
@@ -728,8 +730,8 @@ module Aspera
|
|
|
728
730
|
when :install
|
|
729
731
|
# reset to default location, if older default was used
|
|
730
732
|
Ascp::Installation.instance.sdk_folder = self.class.default_app_main_folder(app_name: APP_NAME_SDK) if @sdk_default_location
|
|
731
|
-
v = Ascp::Installation.instance.install_sdk(options.get_option(:sdk_url, mandatory: true))
|
|
732
|
-
return Main.result_status("Installed version #{v}")
|
|
733
|
+
n, v = Ascp::Installation.instance.install_sdk(options.get_option(:sdk_url, mandatory: true))
|
|
734
|
+
return Main.result_status("Installed #{n} version #{v}")
|
|
733
735
|
when :spec
|
|
734
736
|
return {
|
|
735
737
|
type: :object_list,
|
|
@@ -786,11 +788,11 @@ module Aspera
|
|
|
786
788
|
when :set
|
|
787
789
|
param_name = options.get_next_argument('parameter name')
|
|
788
790
|
param_name = Manager.option_line_to_name(param_name)
|
|
789
|
-
param_value = options.get_next_argument('parameter value')
|
|
791
|
+
param_value = options.get_next_argument('parameter value', validation: nil)
|
|
790
792
|
set_preset_key(name, param_name, param_value)
|
|
791
793
|
return Main.result_nothing
|
|
792
794
|
when :initialize
|
|
793
|
-
config_value = options.get_next_argument('extended value',
|
|
795
|
+
config_value = options.get_next_argument('extended value', validation: Hash)
|
|
794
796
|
if @config_presets.key?(name)
|
|
795
797
|
Log.log.warn{"configuration already exists: #{name}, overwriting"}
|
|
796
798
|
end
|
|
@@ -804,10 +806,10 @@ module Aspera
|
|
|
804
806
|
@config_presets[name].merge!(unprocessed_options)
|
|
805
807
|
return Main.result_status("Updated: #{name}")
|
|
806
808
|
when :ask
|
|
807
|
-
options.ask_missing_mandatory =
|
|
809
|
+
options.ask_missing_mandatory = true
|
|
808
810
|
@config_presets[name] ||= {}
|
|
809
|
-
options.get_next_argument('option names',
|
|
810
|
-
option_value = options.get_interactive(
|
|
811
|
+
options.get_next_argument('option names', multiple: true).each do |option_name|
|
|
812
|
+
option_value = options.get_interactive(option_name, option: true)
|
|
811
813
|
@config_presets[name][option_name] = option_value
|
|
812
814
|
end
|
|
813
815
|
return Main.result_status("Updated: #{name}")
|
|
@@ -870,7 +872,9 @@ module Aspera
|
|
|
870
872
|
check_update
|
|
871
873
|
initdemo
|
|
872
874
|
vault
|
|
873
|
-
throw
|
|
875
|
+
throw
|
|
876
|
+
platform
|
|
877
|
+
].freeze
|
|
874
878
|
|
|
875
879
|
# Main action procedure for plugin
|
|
876
880
|
def execute_action
|
|
@@ -879,16 +883,16 @@ module Aspera
|
|
|
879
883
|
when :preset # newer syntax
|
|
880
884
|
return execute_preset
|
|
881
885
|
when :open
|
|
882
|
-
|
|
886
|
+
Environment.open_editor(@option_config_file.to_s)
|
|
883
887
|
return Main.result_nothing
|
|
884
888
|
when :documentation
|
|
885
889
|
section = options.get_next_argument('private key file path', mandatory: false)
|
|
886
890
|
section = "##{section}" unless section.nil?
|
|
887
|
-
|
|
891
|
+
Environment.instance.open_uri("#{@help}#{section}")
|
|
888
892
|
return Main.result_nothing
|
|
889
893
|
when :genkey # generate new rsa key
|
|
890
894
|
private_key_path = options.get_next_argument('private key file path')
|
|
891
|
-
private_key_length = options.get_next_argument('size in bits', mandatory: false,
|
|
895
|
+
private_key_length = options.get_next_argument('size in bits', mandatory: false, validation: Integer, default: DEFAULT_PRIV_KEY_LENGTH)
|
|
892
896
|
self.class.generate_rsa_private_key(path: private_key_path, length: private_key_length)
|
|
893
897
|
return Main.result_status("Generated #{private_key_length} bit RSA key: #{private_key_path}")
|
|
894
898
|
when :pubkey # get pub key
|
|
@@ -908,7 +912,7 @@ module Aspera
|
|
|
908
912
|
return Main.result_status(remote_chain.first.subject.to_a.find { |name, _, _| name == 'CN' }[1])
|
|
909
913
|
end
|
|
910
914
|
when :echo # display the content of a value given on command line
|
|
911
|
-
return Formatter.auto_type(options.get_next_argument('value'))
|
|
915
|
+
return Formatter.auto_type(options.get_next_argument('value', validation: nil))
|
|
912
916
|
when :flush_tokens
|
|
913
917
|
deleted_files = OAuth::Factory.instance.flush_tokens
|
|
914
918
|
return {type: :value_list, data: deleted_files, name: 'file'}
|
|
@@ -927,8 +931,8 @@ module Aspera
|
|
|
927
931
|
end
|
|
928
932
|
return {type: :object_list, data: result, fields: %w[plugin detect wizard path]}
|
|
929
933
|
when :create
|
|
930
|
-
plugin_name = options.get_next_argument('name'
|
|
931
|
-
destination_folder = options.get_next_argument('folder',
|
|
934
|
+
plugin_name = options.get_next_argument('name').downcase
|
|
935
|
+
destination_folder = options.get_next_argument('folder', mandatory: false) || File.join(@main_folder, ASPERA_PLUGINS_FOLDERNAME)
|
|
932
936
|
plugin_file = File.join(destination_folder, "#{plugin_name}.rb")
|
|
933
937
|
content = <<~END_OF_PLUGIN_CODE
|
|
934
938
|
require 'aspera/cli/plugin'
|
|
@@ -1014,6 +1018,8 @@ module Aspera
|
|
|
1014
1018
|
exception_class = Object.const_get(exception_class_name)
|
|
1015
1019
|
Aspera.assert(exception_class <= Exception){"#{exception_class} is not an exception: #{exception_class.class}"}
|
|
1016
1020
|
raise exception_class, exception_text
|
|
1021
|
+
when :platform
|
|
1022
|
+
return Main.result_status(Environment.architecture)
|
|
1017
1023
|
else Aspera.error_unreachable_line
|
|
1018
1024
|
end
|
|
1019
1025
|
end
|
|
@@ -1077,7 +1083,7 @@ module Aspera
|
|
|
1077
1083
|
Log.log.debug{"wizard result: #{wizard_result}"}
|
|
1078
1084
|
Aspera.assert(WIZARD_RESULT_KEYS.eql?(wizard_result.keys.sort)){"missing or extra keys in wizard result: #{wizard_result.keys}"}
|
|
1079
1085
|
# get preset name from user or default
|
|
1080
|
-
wiz_preset_name =
|
|
1086
|
+
wiz_preset_name = nil
|
|
1081
1087
|
if wiz_preset_name.nil?
|
|
1082
1088
|
elements = [
|
|
1083
1089
|
identification[:product],
|
|
@@ -1217,8 +1223,8 @@ module Aspera
|
|
|
1217
1223
|
when :show
|
|
1218
1224
|
return {type: :single_object, data: vault.get(label: options.get_next_argument('label'))}
|
|
1219
1225
|
when :create
|
|
1220
|
-
label = options.get_next_argument('label',
|
|
1221
|
-
info = options.get_next_argument('info',
|
|
1226
|
+
label = options.get_next_argument('label', validation: String)
|
|
1227
|
+
info = options.get_next_argument('info', validation: Hash)
|
|
1222
1228
|
info = info.symbolize_keys
|
|
1223
1229
|
info[:label] = label
|
|
1224
1230
|
vault.set(info)
|
|
@@ -1270,7 +1276,7 @@ module Aspera
|
|
|
1270
1276
|
info[:password])
|
|
1271
1277
|
when 'system'
|
|
1272
1278
|
case Environment.os
|
|
1273
|
-
when Environment::
|
|
1279
|
+
when Environment::OS_MACOS
|
|
1274
1280
|
@vault = Keychain::MacosSystem.new(info[:name], info[:password])
|
|
1275
1281
|
else
|
|
1276
1282
|
raise 'not implemented for this OS'
|
|
@@ -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'
|
|
@@ -353,9 +354,9 @@ module Aspera
|
|
|
353
354
|
delivery_id = instance_identifier
|
|
354
355
|
raise 'empty id' if delivery_id.empty?
|
|
355
356
|
recipient = options.get_option(:recipient)
|
|
356
|
-
if delivery_id.eql?(
|
|
357
|
+
if delivery_id.eql?(SpecialValues::ALL)
|
|
357
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)}}
|
|
358
|
-
elsif delivery_id.eql?(
|
|
359
|
+
elsif delivery_id.eql?(SpecialValues::INIT)
|
|
359
360
|
Aspera.assert(skip_ids_persistency){'Only with option once_only'}
|
|
360
361
|
skip_ids_persistency.data.clear.concat(mailbox_filtered_entries.map{|i|{id: i[PACKAGE_MATCH_FIELD]}})
|
|
361
362
|
skip_ids_persistency.save
|
|
@@ -390,7 +391,7 @@ module Aspera
|
|
|
390
391
|
headers: {'Accept' => 'application/xml'},
|
|
391
392
|
query: {passcode: link_data[:query]['passcode']})
|
|
392
393
|
if !package_creation_data[:http].body.start_with?('<?xml ')
|
|
393
|
-
|
|
394
|
+
Environment.instance.open_uri(link_url)
|
|
394
395
|
raise Cli::Error, 'Unexpected response: package not found ?'
|
|
395
396
|
end
|
|
396
397
|
package_entry = XmlSimple.xml_in(package_creation_data[:http].body, {'ForceArray' => false})
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
require 'aspera/cli/basic_auth_plugin'
|
|
6
6
|
require 'aspera/cli/extended_value'
|
|
7
|
+
require 'aspera/cli/special_values'
|
|
7
8
|
require 'aspera/persistency_action_once'
|
|
8
9
|
require 'aspera/id_generator'
|
|
9
10
|
require 'aspera/nagios'
|
|
@@ -81,7 +82,7 @@ module Aspera
|
|
|
81
82
|
if options.get_option(:client_id).nil? || options.get_option(:client_secret).nil?
|
|
82
83
|
formatter.display_status('Ask the ascli client id and secret to your Administrator.'.red)
|
|
83
84
|
formatter.display_status("Admin should login to: #{instance_url}")
|
|
84
|
-
|
|
85
|
+
Environment.instance.open_uri(instance_url)
|
|
85
86
|
formatter.display_status('Navigate to: 𓃑 → Admin → Configurations → API clients')
|
|
86
87
|
formatter.display_status('Create an API client with:')
|
|
87
88
|
formatter.display_status('- name: ascli')
|
|
@@ -118,7 +119,7 @@ module Aspera
|
|
|
118
119
|
options.declare(:auth, 'OAuth type of authentication', values: STD_AUTH_TYPES, default: :jwt)
|
|
119
120
|
options.declare(:private_key, 'OAuth JWT RSA private key PEM value (prefix file path with @file:)')
|
|
120
121
|
options.declare(:passphrase, 'OAuth JWT RSA private key passphrase')
|
|
121
|
-
options.declare(:box, "Package inbox, either shared inbox name or one of: #{API_LIST_MAILBOX_TYPES.join(', ')} or #{
|
|
122
|
+
options.declare(:box, "Package inbox, either shared inbox name or one of: #{API_LIST_MAILBOX_TYPES.join(', ')} or #{SpecialValues::ALL}", default: 'inbox')
|
|
122
123
|
options.declare(:shared_folder, 'Send package with files from shared folder')
|
|
123
124
|
options.declare(:group_type, 'Type of shared box', values: %i[shared_inboxes workgroups], default: :shared_inboxes)
|
|
124
125
|
options.parse_options!
|
|
@@ -304,12 +305,12 @@ module Aspera
|
|
|
304
305
|
|
|
305
306
|
# list all packages with optional filter
|
|
306
307
|
def list_packages_with_filter(query: {})
|
|
307
|
-
filter = options.get_next_argument('filter', mandatory: false,
|
|
308
|
+
filter = options.get_next_argument('filter', mandatory: false, validation: Proc, default: ->(_x){true})
|
|
308
309
|
# translate box name to API prefix (with ending slash)
|
|
309
310
|
box = options.get_option(:box)
|
|
310
311
|
real_path =
|
|
311
312
|
case box
|
|
312
|
-
when
|
|
313
|
+
when SpecialValues::ALL then 'packages' # only admin can list all packages globally
|
|
313
314
|
when *API_LIST_MAILBOX_TYPES then "#{box}/packages"
|
|
314
315
|
else
|
|
315
316
|
group_type = options.get_option(:group_type)
|
|
@@ -338,12 +339,12 @@ module Aspera
|
|
|
338
339
|
end
|
|
339
340
|
packages = []
|
|
340
341
|
case package_ids
|
|
341
|
-
when
|
|
342
|
+
when SpecialValues::INIT
|
|
342
343
|
Aspera.assert(skip_ids_persistency){'Only with option once_only'}
|
|
343
344
|
skip_ids_persistency.data.clear.concat(list_packages_with_filter.map{|p|p['id']})
|
|
344
345
|
skip_ids_persistency.save
|
|
345
346
|
return Main.result_status("Initialized skip for #{skip_ids_persistency.data.count} package(s)")
|
|
346
|
-
when
|
|
347
|
+
when SpecialValues::ALL
|
|
347
348
|
# TODO: if packages have same name, they will overwrite ?
|
|
348
349
|
packages = list_packages_with_filter(query: {'status' => 'completed'})
|
|
349
350
|
Log.log.trace1{Log.dump(:package_ids, packages.map{|p|p['id']})}
|
|
@@ -562,10 +563,12 @@ module Aspera
|
|
|
562
563
|
res_command = options.get_next_command(available_commands)
|
|
563
564
|
case res_command
|
|
564
565
|
when *Plugin::ALL_OPS
|
|
565
|
-
return entity_command(
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
566
|
+
return entity_command(
|
|
567
|
+
res_command, adm_api, res_path, item_list_key: list_key, display_fields: display_fields, id_as_arg: id_as_arg,
|
|
568
|
+
delete_style: delete_style) do |field, value|
|
|
569
|
+
lookup_entity_by_field(
|
|
570
|
+
type: res_type, value: value, field: field, real_path: res_path, item_list_key: list_key, query: res_id_query)['id']
|
|
571
|
+
end
|
|
569
572
|
when :shared_folders
|
|
570
573
|
node_id = instance_identifier do |field, value|
|
|
571
574
|
lookup_entity_by_field(type: res_type, field: field, value: value)['id']
|
|
@@ -626,7 +629,7 @@ module Aspera
|
|
|
626
629
|
user
|
|
627
630
|
end
|
|
628
631
|
end
|
|
629
|
-
access = options.get_next_argument('level', mandatory: false,
|
|
632
|
+
access = options.get_next_argument('level', mandatory: false, accept_list: %i[submit_only standard shared_inbox_admin], default: :standard)
|
|
630
633
|
# TODO: unshift to command line parameters instead of using deprecated option "value"
|
|
631
634
|
options.set_option(:value, {user: users.map{|u|{id: u, access: access}}})
|
|
632
635
|
end
|
|
@@ -644,7 +647,7 @@ module Aspera
|
|
|
644
647
|
command = options.get_next_command(%i[configuration smtp resource events clean_deleted].concat(ADMIN_RESOURCES).freeze)
|
|
645
648
|
case command
|
|
646
649
|
when :resource
|
|
647
|
-
# resource
|
|
650
|
+
# resource will be deprecated
|
|
648
651
|
Log.log.warn('resource command is deprecated (4.18), directly use the specific command instead')
|
|
649
652
|
return execute_resource(options.get_next_command(ADMIN_RESOURCES))
|
|
650
653
|
when *ADMIN_RESOURCES
|
|
@@ -722,7 +725,7 @@ module Aspera
|
|
|
722
725
|
when :show
|
|
723
726
|
return { type: :single_object, data: @api_v5.read('account/preferences')[:data] }
|
|
724
727
|
when :modify
|
|
725
|
-
@api_v5.update('account/preferences', options.get_next_argument('modified parameters',
|
|
728
|
+
@api_v5.update('account/preferences', options.get_next_argument('modified parameters', validation: Hash))
|
|
726
729
|
return Main.result_status('modified')
|
|
727
730
|
end
|
|
728
731
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# cspell:ignore snid fnid bidi ssync asyncs rund asnodeadmin mkfile mklink asperabrowser asperabrowserurl watchfolders watchfolderd entsrv
|
|
4
4
|
require 'aspera/cli/basic_auth_plugin'
|
|
5
5
|
require 'aspera/cli/sync_actions'
|
|
6
|
+
require 'aspera/cli/special_values'
|
|
6
7
|
require 'aspera/transfer/spec'
|
|
7
8
|
require 'aspera/nagios'
|
|
8
9
|
require 'aspera/hash_ext'
|
|
@@ -162,7 +163,7 @@ module Aspera
|
|
|
162
163
|
# translates paths results into CLI result, and removes prefix
|
|
163
164
|
def c_result_translate_rem_prefix(response, type, success_msg, path_prefix)
|
|
164
165
|
errors = []
|
|
165
|
-
final_result = { data: [],
|
|
166
|
+
final_result = {type: :object_list, data: [], fields: [type, 'result']}
|
|
166
167
|
JSON.parse(response[:http].body)['paths'].each do |p|
|
|
167
168
|
result = success_msg
|
|
168
169
|
if p.key?('error')
|
|
@@ -179,20 +180,11 @@ module Aspera
|
|
|
179
180
|
return c_result_remove_prefix_path(final_result, type, path_prefix)
|
|
180
181
|
end
|
|
181
182
|
|
|
182
|
-
# get path arguments from command line, and add prefix
|
|
183
|
-
def get_next_arg_add_prefix(path_prefix, name, number=:single)
|
|
184
|
-
path_or_list = options.get_next_argument(name, expected: number)
|
|
185
|
-
return path_or_list if path_prefix.nil?
|
|
186
|
-
return File.join(path_prefix, path_or_list) if path_or_list.is_a?(String)
|
|
187
|
-
return path_or_list.map {|p| File.join(path_prefix, p)} if path_or_list.is_a?(Array)
|
|
188
|
-
raise StandardError, 'expect: nil, String or Array'
|
|
189
|
-
end
|
|
190
|
-
|
|
191
183
|
# directory: node, container: shares
|
|
192
184
|
FOLDER_TYPE = %w[directory container].freeze
|
|
193
185
|
|
|
194
186
|
def browse_gen3(prefix_path)
|
|
195
|
-
folders_to_process = [
|
|
187
|
+
folders_to_process = [get_one_argument_with_prefix(prefix_path, 'path')]
|
|
196
188
|
query = options.get_option(:query, default: {})
|
|
197
189
|
# special parameter: max number of entries in result
|
|
198
190
|
max_items = query.delete('max')
|
|
@@ -254,11 +246,12 @@ module Aspera
|
|
|
254
246
|
def execute_command_gen3(command, prefix_path)
|
|
255
247
|
case command
|
|
256
248
|
when :delete
|
|
257
|
-
|
|
249
|
+
# TODO: add query for recursive
|
|
250
|
+
paths_to_delete = get_all_arguments_with_prefix(prefix_path, 'file list')
|
|
258
251
|
resp = @api_node.create('files/delete', { paths: paths_to_delete.map{|i| {'path' => i.start_with?('/') ? i : "/#{i}"} }})
|
|
259
252
|
return c_result_translate_rem_prefix(resp, 'file', 'deleted', prefix_path)
|
|
260
253
|
when :search
|
|
261
|
-
search_root =
|
|
254
|
+
search_root = get_one_argument_with_prefix(prefix_path, 'search root')
|
|
262
255
|
parameters = {'path' => search_root}
|
|
263
256
|
other_options = query_option
|
|
264
257
|
parameters.merge!(other_options) unless other_options.nil?
|
|
@@ -270,31 +263,30 @@ module Aspera
|
|
|
270
263
|
formatter.display_status("params: #{resp[:data]['parameters'].keys.map{|k|"#{k}:#{resp[:data]['parameters'][k]}"}.join(',')}")
|
|
271
264
|
return c_result_remove_prefix_path(result, 'path', prefix_path)
|
|
272
265
|
when :space
|
|
273
|
-
path_list =
|
|
274
|
-
path_list = [path_list] unless path_list.is_a?(Array)
|
|
266
|
+
path_list = get_all_arguments_with_prefix(prefix_path, 'folder path or ext.val. list')
|
|
275
267
|
resp = @api_node.create('space', { 'paths' => path_list.map {|i| { path: i} } })
|
|
276
|
-
result = { data: resp[:data]['paths']
|
|
268
|
+
result = { type: :object_list, data: resp[:data]['paths']}
|
|
277
269
|
# return c_result_translate_rem_prefix(resp,'folder','created',prefix_path)
|
|
278
270
|
return c_result_remove_prefix_path(result, 'path', prefix_path)
|
|
279
271
|
when :mkdir
|
|
280
|
-
path_list =
|
|
281
|
-
|
|
282
|
-
resp = @api_node.create('files/create', { 'paths' => [{ type: :directory, path: path_list }] })
|
|
272
|
+
path_list = get_all_arguments_with_prefix(prefix_path, 'folder path or ext.val. list')
|
|
273
|
+
resp = @api_node.create('files/create', { 'paths' => path_list.map{|i|{ type: :directory, path: i }}})
|
|
283
274
|
return c_result_translate_rem_prefix(resp, 'folder', 'created', prefix_path)
|
|
284
275
|
when :mklink
|
|
285
|
-
target =
|
|
286
|
-
|
|
287
|
-
resp = @api_node.create('files/create', { 'paths' => [{ type: :symbolic_link, path:
|
|
276
|
+
target = get_one_argument_with_prefix(prefix_path, 'target')
|
|
277
|
+
one_path = get_one_argument_with_prefix(prefix_path, 'link path')
|
|
278
|
+
resp = @api_node.create('files/create', { 'paths' => [{ type: :symbolic_link, path: one_path, target: { path: target} }] })
|
|
288
279
|
return c_result_translate_rem_prefix(resp, 'folder', 'created', prefix_path)
|
|
289
280
|
when :mkfile
|
|
290
|
-
|
|
281
|
+
one_path = get_one_argument_with_prefix(prefix_path, 'file path')
|
|
291
282
|
contents64 = Base64.strict_encode64(options.get_next_argument('contents'))
|
|
292
|
-
resp = @api_node.create('files/create', { 'paths' => [{ type: :file, path:
|
|
283
|
+
resp = @api_node.create('files/create', { 'paths' => [{ type: :file, path: one_path, contents: contents64 }] })
|
|
293
284
|
return c_result_translate_rem_prefix(resp, 'folder', 'created', prefix_path)
|
|
294
285
|
when :rename
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
286
|
+
# TODO: multiple ?
|
|
287
|
+
path_base = get_one_argument_with_prefix(prefix_path, 'path_base')
|
|
288
|
+
path_src = get_one_argument_with_prefix(prefix_path, 'path_src')
|
|
289
|
+
path_dst = get_one_argument_with_prefix(prefix_path, 'path_dst')
|
|
298
290
|
resp = @api_node.create('files/rename', { 'paths' => [{ 'path' => path_base, 'source' => path_src, 'destination' => path_dst }] })
|
|
299
291
|
return c_result_translate_rem_prefix(resp, 'entry', 'moved', prefix_path)
|
|
300
292
|
when :browse
|
|
@@ -346,7 +338,7 @@ module Aspera
|
|
|
346
338
|
transfer_spec.delete('paths') if command.eql?(:upload)
|
|
347
339
|
return Main.result_transfer(transfer.start(transfer_spec))
|
|
348
340
|
when :http_node_download
|
|
349
|
-
remote_path =
|
|
341
|
+
remote_path = get_one_argument_with_prefix(prefix_path, 'remote path')
|
|
350
342
|
file_name = File.basename(remote_path)
|
|
351
343
|
@api_node.call(
|
|
352
344
|
operation: 'GET',
|
|
@@ -390,7 +382,7 @@ module Aspera
|
|
|
390
382
|
when :set_bearer_key
|
|
391
383
|
access_key_id = options.get_next_argument('access key id')
|
|
392
384
|
access_key_id = @api_node.read('access_keys/self')[:data]['id'] if access_key_id.eql?('self')
|
|
393
|
-
bearer_key_pem = options.get_next_argument('public or private RSA key PEM value',
|
|
385
|
+
bearer_key_pem = options.get_next_argument('public or private RSA key PEM value', validation: String)
|
|
394
386
|
key = OpenSSL::PKey.read(bearer_key_pem)
|
|
395
387
|
key = key.public_key if key.private?
|
|
396
388
|
bearer_key_pem = key.to_pem
|
|
@@ -539,16 +531,17 @@ module Aspera
|
|
|
539
531
|
# if a single file: split into folder and path
|
|
540
532
|
apifid = @api_node.resolve_api_fid(top_file_id, source_folder)
|
|
541
533
|
if source_paths.empty?
|
|
534
|
+
# get precise info in this element
|
|
542
535
|
file_info = apifid[:api].read("files/#{apifid[:file_id]}")[:data]
|
|
543
536
|
case file_info['type']
|
|
544
537
|
when 'file'
|
|
545
538
|
# if the single source is a file, we need to split into folder path and filename
|
|
546
539
|
src_dir_elements = source_folder.split(Api::Node::PATH_SEPARATOR)
|
|
547
|
-
# filename is the last one
|
|
540
|
+
# filename is the last one, source folder is what remains
|
|
548
541
|
source_paths = [{'source' => src_dir_elements.pop}]
|
|
549
|
-
#
|
|
542
|
+
# add trailing / so that link is resolved, if it's a shared folder
|
|
543
|
+
src_dir_elements.push('')
|
|
550
544
|
source_folder = src_dir_elements.join(Api::Node::PATH_SEPARATOR)
|
|
551
|
-
# TODO: instead of creating a new object, use the same, and change file id with parent folder id ? possible ?
|
|
552
545
|
apifid = @api_node.resolve_api_fid(top_file_id, source_folder)
|
|
553
546
|
when 'link', 'folder'
|
|
554
547
|
# single source is 'folder' or 'link'
|
|
@@ -581,7 +574,7 @@ module Aspera
|
|
|
581
574
|
return {type: :single_object, data: items}
|
|
582
575
|
when :modify
|
|
583
576
|
apifid = apifid_from_next_arg(top_file_id)
|
|
584
|
-
update_param = options.get_next_argument('update data',
|
|
577
|
+
update_param = options.get_next_argument('update data', validation: Hash)
|
|
585
578
|
apifid[:api].update("files/#{apifid[:file_id]}", update_param)[:data]
|
|
586
579
|
return Main.result_status('Done')
|
|
587
580
|
when :thumbnail
|
|
@@ -612,7 +605,7 @@ module Aspera
|
|
|
612
605
|
{'id' => one_id}
|
|
613
606
|
end
|
|
614
607
|
when :create
|
|
615
|
-
create_param = options.get_next_argument('creation data',
|
|
608
|
+
create_param = options.get_next_argument('creation data', validation: Hash)
|
|
616
609
|
raise 'no file_id' if create_param.key?('file_id')
|
|
617
610
|
create_param['file_id'] = apifid[:file_id]
|
|
618
611
|
create_param['access_levels'] = Api::Node::ACCESS_LEVELS unless create_param.key?('access_levels')
|
|
@@ -638,7 +631,7 @@ module Aspera
|
|
|
638
631
|
async_name = options.get_option(:sync_name)
|
|
639
632
|
if async_name.nil?
|
|
640
633
|
async_id = instance_identifier
|
|
641
|
-
if async_id.eql?(
|
|
634
|
+
if async_id.eql?(SpecialValues::ALL) && %i[show delete].include?(command)
|
|
642
635
|
async_ids = @api_node.read('async/list')[:data]['sync_ids']
|
|
643
636
|
else
|
|
644
637
|
Integer(async_id) # must be integer
|
|
@@ -661,7 +654,7 @@ module Aspera
|
|
|
661
654
|
when :show
|
|
662
655
|
resp = @api_node.create('async/summary', post_data)[:data]['sync_summaries']
|
|
663
656
|
return Main.result_empty if resp.empty?
|
|
664
|
-
return { type: :object_list, data: resp, fields: %w[snid name local_dir remote_dir] } if async_id.eql?(
|
|
657
|
+
return { type: :object_list, data: resp, fields: %w[snid name local_dir remote_dir] } if async_id.eql?(SpecialValues::ALL)
|
|
665
658
|
return { type: :single_object, data: resp.first }
|
|
666
659
|
when :delete
|
|
667
660
|
resp = @api_node.create('async/delete', post_data)[:data]
|
|
@@ -815,7 +808,7 @@ module Aspera
|
|
|
815
808
|
resp = @api_node.read(one_res_path)
|
|
816
809
|
return { type: :other_struct, data: resp[:data] }
|
|
817
810
|
when :modify
|
|
818
|
-
resp = @api_node.update(one_res_path, options.get_next_argument('update value',
|
|
811
|
+
resp = @api_node.update(one_res_path, options.get_next_argument('update value', validation: Hash))
|
|
819
812
|
return { type: :other_struct, data: resp[:data] }
|
|
820
813
|
when :bandwidth_average
|
|
821
814
|
transfers_data = @api_node.read(res_class_path, query_read_delete)[:data]
|
|
@@ -876,7 +869,7 @@ module Aspera
|
|
|
876
869
|
return { type: :object_list, data: resp[:data]['services'] }
|
|
877
870
|
when :create
|
|
878
871
|
# @json:'{"type":"WATCHFOLDERD","run_as":{"user":"user1"}}'
|
|
879
|
-
params = options.get_next_argument('
|
|
872
|
+
params = options.get_next_argument('creation data', validation: Hash)
|
|
880
873
|
resp = @api_node.create('rund/services', params)
|
|
881
874
|
return Main.result_status("#{resp[:data]['id']} created")
|
|
882
875
|
when :delete
|
|
@@ -952,13 +945,13 @@ module Aspera
|
|
|
952
945
|
}
|
|
953
946
|
# encode parameters so that it looks good in url
|
|
954
947
|
encoded_params = Base64.strict_encode64(Zlib::Deflate.deflate(JSON.generate(browse_params))).gsub(/=+$/, '').tr('+/', '-_').reverse
|
|
955
|
-
|
|
948
|
+
Environment.instance.open_uri("#{options.get_option(:asperabrowserurl)}?goto=#{encoded_params}")
|
|
956
949
|
return Main.result_status('done')
|
|
957
950
|
when :basic_token
|
|
958
951
|
return Main.result_status(Rest.basic_token(options.get_option(:username, mandatory: true), options.get_option(:password, mandatory: true)))
|
|
959
952
|
when :bearer_token
|
|
960
|
-
private_key = OpenSSL::PKey::RSA.new(options.get_next_argument('private RSA key PEM value',
|
|
961
|
-
token_info = options.get_next_argument('user and group identification',
|
|
953
|
+
private_key = OpenSSL::PKey::RSA.new(options.get_next_argument('private RSA key PEM value', validation: String))
|
|
954
|
+
token_info = options.get_next_argument('user and group identification', validation: Hash)
|
|
962
955
|
access_key = options.get_option(:username, mandatory: true)
|
|
963
956
|
return Main.result_status(Api::Node.bearer_token(payload: token_info, access_key: access_key, private_key: private_key))
|
|
964
957
|
when :simulator
|
|
@@ -974,6 +967,22 @@ module Aspera
|
|
|
974
967
|
end
|
|
975
968
|
raise 'ERROR: shall not reach this line'
|
|
976
969
|
end
|
|
970
|
+
|
|
971
|
+
private
|
|
972
|
+
|
|
973
|
+
# get remaining path arguments from command line, and add prefix
|
|
974
|
+
def get_all_arguments_with_prefix(path_prefix, name)
|
|
975
|
+
path_args = options.get_next_argument(name, multiple: true)
|
|
976
|
+
return path_args if path_prefix.nil?
|
|
977
|
+
return path_args.map {|p| File.join(path_prefix, p)}
|
|
978
|
+
end
|
|
979
|
+
|
|
980
|
+
# get next path argument from command line, and add prefix
|
|
981
|
+
def get_one_argument_with_prefix(path_prefix, name)
|
|
982
|
+
path_arg = options.get_next_argument(name, validation: String)
|
|
983
|
+
return path_arg if path_prefix.nil?
|
|
984
|
+
return File.join(path_prefix, path_arg)
|
|
985
|
+
end
|
|
977
986
|
end
|
|
978
987
|
end
|
|
979
988
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'aspera/cli/basic_auth_plugin'
|
|
4
|
+
require 'aspera/cli/special_values'
|
|
4
5
|
require 'aspera/nagios'
|
|
5
6
|
require 'aspera/log'
|
|
6
7
|
require 'aspera/assert'
|
|
@@ -150,7 +151,7 @@ module Aspera
|
|
|
150
151
|
end
|
|
151
152
|
case command
|
|
152
153
|
when :status
|
|
153
|
-
wf_id = nil if wf_id.eql?(
|
|
154
|
+
wf_id = nil if wf_id.eql?(SpecialValues::ALL)
|
|
154
155
|
result = call_ao('workflows_status', id: wf_id)[:data]
|
|
155
156
|
return {type: :object_list, data: result['workflows']['workflow']}
|
|
156
157
|
when :list
|
|
@@ -176,7 +177,7 @@ module Aspera
|
|
|
176
177
|
}
|
|
177
178
|
call_params = {format: :json}
|
|
178
179
|
# get external parameters if any
|
|
179
|
-
options.get_next_argument('external_parameters', mandatory: false,
|
|
180
|
+
options.get_next_argument('external_parameters', mandatory: false, validation: Hash, default: {}).each do |name, value|
|
|
180
181
|
call_params["external_parameters[#{name}]"] = value
|
|
181
182
|
end
|
|
182
183
|
# synchronous call ?
|
|
@@ -489,7 +489,7 @@ module Aspera
|
|
|
489
489
|
return Main.result_status('Tools validated')
|
|
490
490
|
when :test, :show
|
|
491
491
|
source = options.get_next_argument('source file')
|
|
492
|
-
format = options.get_next_argument('format',
|
|
492
|
+
format = options.get_next_argument('format', accept_list: Aspera::Preview::Generator::PREVIEW_FORMATS, default: :png)
|
|
493
493
|
generated_file_path = preview_filename(format, options.get_option(:base))
|
|
494
494
|
g = Aspera::Preview::Generator.new(source, generated_file_path, @gen_options, @tmp_folder, nil)
|
|
495
495
|
g.generate
|
|
@@ -176,7 +176,7 @@ module Aspera
|
|
|
176
176
|
def execute_transfer(command, transfer_spec)
|
|
177
177
|
case command
|
|
178
178
|
when :upload, :download
|
|
179
|
-
Transfer::Spec.
|
|
179
|
+
transfer_spec['direction'] = Transfer::Spec.transfer_type_to_direction(command)
|
|
180
180
|
return Main.result_transfer(transfer.start(transfer_spec))
|
|
181
181
|
when :sync
|
|
182
182
|
# lets ignore the arguments provided by execute_sync_action, we just give the transfer spec
|
|
@@ -232,7 +232,7 @@ module Aspera
|
|
|
232
232
|
when *TRANSFER_COMMANDS
|
|
233
233
|
return execute_transfer(command, server_transfer_spec)
|
|
234
234
|
when *AsCmd::OPERATIONS
|
|
235
|
-
command_arguments = options.get_next_argument('ascmd command arguments',
|
|
235
|
+
command_arguments = options.get_next_argument('ascmd command arguments', multiple: true, mandatory: false)
|
|
236
236
|
ascmd = AsCmd.new(ascmd_executor)
|
|
237
237
|
begin
|
|
238
238
|
result = ascmd.execute_single(command, command_arguments)
|