aspera-cli 4.18.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 -2
- data/CHANGELOG.md +10 -0
- data/README.md +96 -59
- data/examples/build_package.sh +28 -0
- data/lib/aspera/agent/alpha.rb +4 -4
- data/lib/aspera/agent/connect.rb +3 -4
- data/lib/aspera/agent/httpgw.rb +1 -1
- data/lib/aspera/api/httpgw.rb +4 -1
- data/lib/aspera/api/node.rb +110 -77
- data/lib/aspera/ascp/products.rb +1 -1
- data/lib/aspera/cli/extended_value.rb +27 -14
- data/lib/aspera/cli/formatter.rb +11 -10
- data/lib/aspera/cli/main.rb +11 -11
- data/lib/aspera/cli/manager.rb +99 -84
- data/lib/aspera/cli/plugin.rb +2 -5
- data/lib/aspera/cli/plugins/aoc.rb +15 -14
- data/lib/aspera/cli/plugins/config.rb +20 -19
- 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 +46 -38
- 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 +1 -1
- data/lib/aspera/cli/special_values.rb +13 -0
- data/lib/aspera/cli/sync_actions.rb +4 -4
- data/lib/aspera/cli/transfer_agent.rb +2 -2
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/environment.rb +64 -4
- data/lib/aspera/oauth/web.rb +2 -2
- data/lib/aspera/rest.rb +46 -15
- data.tar.gz.sig +0 -0
- metadata +4 -3
- metadata.gz.sig +0 -0
- data/lib/aspera/open_application.rb +0 -69
@@ -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
|
@@ -581,7 +573,7 @@ module Aspera
|
|
581
573
|
return {type: :single_object, data: items}
|
582
574
|
when :modify
|
583
575
|
apifid = apifid_from_next_arg(top_file_id)
|
584
|
-
update_param = options.get_next_argument('update data',
|
576
|
+
update_param = options.get_next_argument('update data', validation: Hash)
|
585
577
|
apifid[:api].update("files/#{apifid[:file_id]}", update_param)[:data]
|
586
578
|
return Main.result_status('Done')
|
587
579
|
when :thumbnail
|
@@ -612,7 +604,7 @@ module Aspera
|
|
612
604
|
{'id' => one_id}
|
613
605
|
end
|
614
606
|
when :create
|
615
|
-
create_param = options.get_next_argument('creation data',
|
607
|
+
create_param = options.get_next_argument('creation data', validation: Hash)
|
616
608
|
raise 'no file_id' if create_param.key?('file_id')
|
617
609
|
create_param['file_id'] = apifid[:file_id]
|
618
610
|
create_param['access_levels'] = Api::Node::ACCESS_LEVELS unless create_param.key?('access_levels')
|
@@ -638,7 +630,7 @@ module Aspera
|
|
638
630
|
async_name = options.get_option(:sync_name)
|
639
631
|
if async_name.nil?
|
640
632
|
async_id = instance_identifier
|
641
|
-
if async_id.eql?(
|
633
|
+
if async_id.eql?(SpecialValues::ALL) && %i[show delete].include?(command)
|
642
634
|
async_ids = @api_node.read('async/list')[:data]['sync_ids']
|
643
635
|
else
|
644
636
|
Integer(async_id) # must be integer
|
@@ -661,7 +653,7 @@ module Aspera
|
|
661
653
|
when :show
|
662
654
|
resp = @api_node.create('async/summary', post_data)[:data]['sync_summaries']
|
663
655
|
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?(
|
656
|
+
return { type: :object_list, data: resp, fields: %w[snid name local_dir remote_dir] } if async_id.eql?(SpecialValues::ALL)
|
665
657
|
return { type: :single_object, data: resp.first }
|
666
658
|
when :delete
|
667
659
|
resp = @api_node.create('async/delete', post_data)[:data]
|
@@ -815,7 +807,7 @@ module Aspera
|
|
815
807
|
resp = @api_node.read(one_res_path)
|
816
808
|
return { type: :other_struct, data: resp[:data] }
|
817
809
|
when :modify
|
818
|
-
resp = @api_node.update(one_res_path, options.get_next_argument('update value',
|
810
|
+
resp = @api_node.update(one_res_path, options.get_next_argument('update value', validation: Hash))
|
819
811
|
return { type: :other_struct, data: resp[:data] }
|
820
812
|
when :bandwidth_average
|
821
813
|
transfers_data = @api_node.read(res_class_path, query_read_delete)[:data]
|
@@ -876,7 +868,7 @@ module Aspera
|
|
876
868
|
return { type: :object_list, data: resp[:data]['services'] }
|
877
869
|
when :create
|
878
870
|
# @json:'{"type":"WATCHFOLDERD","run_as":{"user":"user1"}}'
|
879
|
-
params = options.get_next_argument('
|
871
|
+
params = options.get_next_argument('creation data', validation: Hash)
|
880
872
|
resp = @api_node.create('rund/services', params)
|
881
873
|
return Main.result_status("#{resp[:data]['id']} created")
|
882
874
|
when :delete
|
@@ -952,13 +944,13 @@ module Aspera
|
|
952
944
|
}
|
953
945
|
# encode parameters so that it looks good in url
|
954
946
|
encoded_params = Base64.strict_encode64(Zlib::Deflate.deflate(JSON.generate(browse_params))).gsub(/=+$/, '').tr('+/', '-_').reverse
|
955
|
-
|
947
|
+
Environment.instance.open_uri("#{options.get_option(:asperabrowserurl)}?goto=#{encoded_params}")
|
956
948
|
return Main.result_status('done')
|
957
949
|
when :basic_token
|
958
950
|
return Main.result_status(Rest.basic_token(options.get_option(:username, mandatory: true), options.get_option(:password, mandatory: true)))
|
959
951
|
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',
|
952
|
+
private_key = OpenSSL::PKey::RSA.new(options.get_next_argument('private RSA key PEM value', validation: String))
|
953
|
+
token_info = options.get_next_argument('user and group identification', validation: Hash)
|
962
954
|
access_key = options.get_option(:username, mandatory: true)
|
963
955
|
return Main.result_status(Api::Node.bearer_token(payload: token_info, access_key: access_key, private_key: private_key))
|
964
956
|
when :simulator
|
@@ -974,6 +966,22 @@ module Aspera
|
|
974
966
|
end
|
975
967
|
raise 'ERROR: shall not reach this line'
|
976
968
|
end
|
969
|
+
|
970
|
+
private
|
971
|
+
|
972
|
+
# get remaining path arguments from command line, and add prefix
|
973
|
+
def get_all_arguments_with_prefix(path_prefix, name)
|
974
|
+
path_args = options.get_next_argument(name, multiple: true)
|
975
|
+
return path_args if path_prefix.nil?
|
976
|
+
return path_args.map {|p| File.join(path_prefix, p)}
|
977
|
+
end
|
978
|
+
|
979
|
+
# get next path argument from command line, and add prefix
|
980
|
+
def get_one_argument_with_prefix(path_prefix, name)
|
981
|
+
path_arg = options.get_next_argument(name, validation: String)
|
982
|
+
return path_arg if path_prefix.nil?
|
983
|
+
return File.join(path_prefix, path_arg)
|
984
|
+
end
|
977
985
|
end
|
978
986
|
end
|
979
987
|
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
|
@@ -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)
|
@@ -29,9 +29,9 @@ module Aspera
|
|
29
29
|
SIMPLE_ARGUMENTS_SYNC.each do |arg, check|
|
30
30
|
value = options.get_next_argument(
|
31
31
|
arg,
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
mandatory: false,
|
33
|
+
validation: check.is_a?(Class) ? check : nil,
|
34
|
+
accept_list: check.is_a?(Class) ? nil : check)
|
35
35
|
break if value.nil?
|
36
36
|
simple_session_args[arg] = value.to_s
|
37
37
|
end
|
@@ -57,7 +57,7 @@ module Aspera
|
|
57
57
|
command2 = options.get_next_command([:status])
|
58
58
|
case command2
|
59
59
|
when :status
|
60
|
-
sync_session_name = options.get_next_argument('name of sync session', mandatory: false,
|
60
|
+
sync_session_name = options.get_next_argument('name of sync session', mandatory: false, validation: String)
|
61
61
|
async_params = options.get_option(:sync_info, mandatory: true)
|
62
62
|
return {type: :single_object, data: Transfer::Sync.admin_status(async_params, sync_session_name)}
|
63
63
|
end
|
@@ -175,7 +175,7 @@ module Aspera
|
|
175
175
|
when nil, FILE_LIST_FROM_ARGS
|
176
176
|
Log.log.debug('getting file list as parameters')
|
177
177
|
# get remaining arguments
|
178
|
-
file_list = @opt_mgr.get_next_argument('source file list',
|
178
|
+
file_list = @opt_mgr.get_next_argument('source file list', multiple: true)
|
179
179
|
raise Cli::BadArgument, 'specify at least one file on command line or use ' \
|
180
180
|
"--sources=#{FILE_LIST_FROM_TRANSFER_SPEC} to use transfer spec" if !file_list.is_a?(Array) || file_list.empty?
|
181
181
|
when FILE_LIST_FROM_TRANSFER_SPEC
|
@@ -244,7 +244,7 @@ module Aspera
|
|
244
244
|
updated_ts(transfer_spec)
|
245
245
|
# if TS from app has content_protection (e.g. F5), that means content is protected: ask password if not provided
|
246
246
|
if transfer_spec['content_protection'].eql?('decrypt') && !transfer_spec.key?('content_protection_password')
|
247
|
-
transfer_spec['content_protection_password'] = @opt_mgr.prompt_user_input('content protection password', true)
|
247
|
+
transfer_spec['content_protection_password'] = @opt_mgr.prompt_user_input('content protection password', sensitive: true)
|
248
248
|
end
|
249
249
|
# create transfer agent
|
250
250
|
agent_instance.start_transfer(transfer_spec, token_regenerator: rest_token)
|
data/lib/aspera/cli/version.rb
CHANGED
data/lib/aspera/environment.rb
CHANGED
@@ -4,17 +4,21 @@
|
|
4
4
|
require 'aspera/log'
|
5
5
|
require 'aspera/assert'
|
6
6
|
require 'rbconfig'
|
7
|
+
require 'singleton'
|
7
8
|
|
8
9
|
# cspell:words MEBI mswin bccwin
|
9
10
|
|
10
11
|
module Aspera
|
11
12
|
# detect OS, architecture, and specific stuff
|
12
13
|
class Environment
|
14
|
+
include Singleton
|
15
|
+
USER_INTERFACES = %i[text graphical].freeze
|
16
|
+
|
13
17
|
OS_WINDOWS = :windows
|
14
|
-
|
18
|
+
OS_MACOS = :osx
|
15
19
|
OS_LINUX = :linux
|
16
20
|
OS_AIX = :aix
|
17
|
-
OS_LIST = [OS_WINDOWS,
|
21
|
+
OS_LIST = [OS_WINDOWS, OS_MACOS, OS_LINUX, OS_AIX].freeze
|
18
22
|
CPU_X86_64 = :x86_64
|
19
23
|
CPU_ARM64 = :arm64
|
20
24
|
CPU_PPC64 = :ppc64
|
@@ -37,7 +41,7 @@ module Aspera
|
|
37
41
|
when /mswin/, /msys/, /mingw/, /cygwin/, /bccwin/, /wince/, /emc/
|
38
42
|
return OS_WINDOWS
|
39
43
|
when /darwin/, /mac os/
|
40
|
-
return
|
44
|
+
return OS_MACOS
|
41
45
|
when /linux/
|
42
46
|
return OS_LINUX
|
43
47
|
when /aix/
|
@@ -122,10 +126,66 @@ module Aspera
|
|
122
126
|
end
|
123
127
|
|
124
128
|
# @return true if we can display Unicode characters
|
129
|
+
# https://www.gnu.org/software/libc/manual/html_node/Locale-Categories.html
|
130
|
+
# https://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html
|
125
131
|
def terminal_supports_unicode?
|
126
|
-
@terminal_supports_unicode = terminal? &&
|
132
|
+
@terminal_supports_unicode = terminal? && %w(LC_ALL LC_CTYPE LANG).any?{|var|ENV[var]&.include?('UTF-8')} if @terminal_supports_unicode.nil?
|
127
133
|
return @terminal_supports_unicode
|
128
134
|
end
|
135
|
+
|
136
|
+
def default_gui_mode
|
137
|
+
# assume not remotely connected on macos and windows
|
138
|
+
return :graphical if [Environment::OS_WINDOWS, Environment::OS_MACOS].include?(Environment.os)
|
139
|
+
# unix family
|
140
|
+
return :graphical if ENV.key?('DISPLAY') && !ENV['DISPLAY'].empty?
|
141
|
+
return :text
|
142
|
+
end
|
143
|
+
|
144
|
+
# command must be non blocking
|
145
|
+
def open_uri_graphical(uri)
|
146
|
+
case Environment.os
|
147
|
+
when Environment::OS_MACOS then return system('open', uri.to_s)
|
148
|
+
when Environment::OS_WINDOWS then return system('start', 'explorer', %Q{"#{uri}"})
|
149
|
+
when Environment::OS_LINUX then return system('xdg-open', uri.to_s)
|
150
|
+
else
|
151
|
+
raise "no graphical open method for #{Environment.os}"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def open_editor(file_path)
|
156
|
+
if ENV.key?('EDITOR')
|
157
|
+
system(ENV['EDITOR'], file_path.to_s)
|
158
|
+
elsif Environment.os.eql?(Environment::OS_WINDOWS)
|
159
|
+
system('notepad.exe', %Q{"#{file_path}"})
|
160
|
+
else
|
161
|
+
open_uri_graphical(file_path.to_s)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
attr_accessor :url_method
|
166
|
+
|
167
|
+
def initialize
|
168
|
+
@url_method = self.class.default_gui_mode
|
169
|
+
end
|
170
|
+
|
171
|
+
# Allows a user to open a Url
|
172
|
+
# if method is "text", then URL is displayed on terminal
|
173
|
+
# if method is "graphical", then the URL will be opened with the default browser.
|
174
|
+
# this is non blocking
|
175
|
+
def open_uri(the_url)
|
176
|
+
case @url_method
|
177
|
+
when :graphical
|
178
|
+
self.class.open_uri_graphical(the_url)
|
179
|
+
when :text
|
180
|
+
case the_url.to_s
|
181
|
+
when /^http/
|
182
|
+
puts "USER ACTION: please enter this url in a browser:\n#{the_url.to_s.red}\n"
|
183
|
+
else
|
184
|
+
puts "USER ACTION: open this:\n#{the_url.to_s.red}\n"
|
185
|
+
end
|
186
|
+
else
|
187
|
+
raise StandardError, "unsupported url open method: #{@url_method}"
|
188
|
+
end
|
129
189
|
end
|
130
190
|
end
|
131
191
|
end
|
data/lib/aspera/oauth/web.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'aspera/oauth/base'
|
4
|
-
require 'aspera/
|
4
|
+
require 'aspera/environment'
|
5
5
|
require 'aspera/web_auth'
|
6
6
|
require 'aspera/assert'
|
7
7
|
module Aspera
|
@@ -34,7 +34,7 @@ module Aspera
|
|
34
34
|
# start a web server to receive request code
|
35
35
|
web_server = WebAuth.new(@redirect_uri)
|
36
36
|
# start browser on login page
|
37
|
-
|
37
|
+
Environment.instance.open_uri(login_page_url)
|
38
38
|
# wait for code in request
|
39
39
|
received_params = web_server.received_request
|
40
40
|
Aspera.assert(random_state.eql?(received_params['state'])){'wrong received state'}
|