aspera-cli 4.20.0 → 4.21.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 +20 -2
- data/README.md +281 -156
- data/bin/asession +2 -2
- data/lib/aspera/agent/alpha.rb +7 -12
- data/lib/aspera/agent/connect.rb +19 -1
- data/lib/aspera/agent/direct.rb +20 -29
- data/lib/aspera/agent/node.rb +1 -11
- data/lib/aspera/agent/trsdk.rb +4 -25
- data/lib/aspera/api/aoc.rb +5 -0
- data/lib/aspera/api/node.rb +45 -28
- data/lib/aspera/ascp/installation.rb +69 -38
- data/lib/aspera/ascp/management.rb +27 -6
- data/lib/aspera/cli/formatter.rb +149 -141
- data/lib/aspera/cli/info.rb +1 -1
- data/lib/aspera/cli/manager.rb +1 -0
- data/lib/aspera/cli/plugin.rb +2 -2
- data/lib/aspera/cli/plugins/aoc.rb +27 -17
- data/lib/aspera/cli/plugins/config.rb +31 -21
- data/lib/aspera/cli/plugins/faspex.rb +1 -1
- data/lib/aspera/cli/plugins/faspex5.rb +11 -3
- data/lib/aspera/cli/plugins/node.rb +44 -38
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/command_line_builder.rb +1 -1
- data/lib/aspera/environment.rb +5 -6
- data/lib/aspera/node_simulator.rb +228 -112
- data/lib/aspera/oauth/base.rb +31 -42
- data/lib/aspera/oauth/factory.rb +41 -2
- data/lib/aspera/persistency_folder.rb +20 -2
- data/lib/aspera/preview/generator.rb +1 -1
- data/lib/aspera/preview/utils.rb +1 -1
- data/lib/aspera/products/alpha.rb +30 -0
- data/lib/aspera/products/connect.rb +48 -0
- data/lib/aspera/products/other.rb +82 -0
- data/lib/aspera/products/trsdk.rb +54 -0
- data/lib/aspera/rest.rb +18 -13
- data/lib/aspera/ssh.rb +28 -24
- data/lib/aspera/transfer/spec.yaml +22 -20
- data.tar.gz.sig +0 -0
- metadata +21 -4
- metadata.gz.sig +0 -0
- data/lib/aspera/ascp/products.rb +0 -168
data/lib/aspera/cli/plugin.rb
CHANGED
@@ -220,12 +220,12 @@ module Aspera
|
|
220
220
|
query = options.get_option(:query)
|
221
221
|
# dup default, as it could be frozen
|
222
222
|
query = default.dup if query.nil?
|
223
|
-
Log.log.debug{"
|
223
|
+
Log.log.debug{"query_read_delete=#{query}".bg_red}
|
224
224
|
begin
|
225
225
|
# check it is suitable
|
226
226
|
URI.encode_www_form(query) unless query.nil?
|
227
227
|
rescue StandardError => e
|
228
|
-
raise Cli::BadArgument, "Query must be an extended value which can be encoded with URI.encode_www_form. Refer to manual. (#{e.message})"
|
228
|
+
raise Cli::BadArgument, "Query must be an extended value (Hash, Array) which can be encoded with URI.encode_www_form. Refer to manual. (#{e.message})"
|
229
229
|
end
|
230
230
|
return query
|
231
231
|
end
|
@@ -66,14 +66,14 @@ module Aspera
|
|
66
66
|
base_url = "#{base_url}.#{Api::AoC::SAAS_DOMAIN_PROD}" unless base_url.include?('.')
|
67
67
|
# AoC is only https
|
68
68
|
return nil unless base_url.start_with?('https://')
|
69
|
-
res_http = Rest.new(base_url: base_url, redirect_max:
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
69
|
+
res_http = Rest.new(base_url: base_url, redirect_max: 0).call(operation: 'GET', subpath: 'auth/ping', return_error: true)[:http]
|
70
|
+
return nil if res_http['Location'].nil?
|
71
|
+
redirect_uri = URI.parse(res_http['Location'])
|
72
|
+
od = Api::AoC.split_org_domain(URI.parse(base_url))
|
73
|
+
return nil unless redirect_uri.path.end_with?("oauth2/#{od[:organization]}/login")
|
74
74
|
# either in standard domain, or product name in page
|
75
75
|
return {
|
76
|
-
version: 'SaaS',
|
76
|
+
version: Api::AoC.saas_url?(base_url) ? 'SaaS' : 'Self-managed',
|
77
77
|
url: base_url
|
78
78
|
}
|
79
79
|
end
|
@@ -92,8 +92,6 @@ module Aspera
|
|
92
92
|
# set vars to look like object
|
93
93
|
options = object.options
|
94
94
|
formatter = object.formatter
|
95
|
-
options.declare(:use_generic_client, 'Wizard: AoC: use global or org specific jwt client id', values: :bool, default: true)
|
96
|
-
options.parse_options!
|
97
95
|
instance_url = options.get_option(:url, mandatory: true)
|
98
96
|
pub_link_info = Api::AoC.link_info(instance_url)
|
99
97
|
if !pub_link_info[:token].nil?
|
@@ -108,6 +106,8 @@ module Aspera
|
|
108
106
|
test_args: 'organization'
|
109
107
|
}
|
110
108
|
end
|
109
|
+
options.declare(:use_generic_client, 'Wizard: AoC: use global or org specific jwt client id', values: :bool, default: Api::AoC.saas_url?(instance_url))
|
110
|
+
options.parse_options!
|
111
111
|
# make username mandatory for jwt, this triggers interactive input
|
112
112
|
wiz_username = options.get_option(:username, mandatory: true)
|
113
113
|
raise "Username shall be an email in AoC: #{wiz_username}" if !(wiz_username =~ /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i)
|
@@ -133,15 +133,15 @@ module Aspera
|
|
133
133
|
formatter.display_status('Please login to your Aspera on Cloud instance.'.red)
|
134
134
|
formatter.display_status('Navigate to: 𓃑 → Admin → Integrations → API Clients')
|
135
135
|
formatter.display_status('Check or create in integration:')
|
136
|
-
formatter.display_status(
|
136
|
+
formatter.display_status('- name: cli')
|
137
137
|
formatter.display_status("- redirect uri: #{REDIRECT_LOCALHOST}")
|
138
138
|
formatter.display_status('- origin: localhost')
|
139
139
|
formatter.display_status('Use the generated client id and secret in the following prompts.'.red)
|
140
140
|
end
|
141
|
-
Environment.instance.open_uri("#{instance_url}/admin/api-clients")
|
141
|
+
Environment.instance.open_uri("#{instance_url}/admin/integrations/api-clients")
|
142
142
|
options.get_option(:client_id, mandatory: true)
|
143
143
|
options.get_option(:client_secret, mandatory: true)
|
144
|
-
use_browser_authentication = true
|
144
|
+
# use_browser_authentication = true
|
145
145
|
end
|
146
146
|
if use_browser_authentication
|
147
147
|
formatter.display_status('We will use web authentication to bootstrap.')
|
@@ -282,13 +282,17 @@ module Aspera
|
|
282
282
|
end
|
283
283
|
|
284
284
|
# list all entities, given additional, default and user's queries
|
285
|
+
# @param resource_class_path path to query on API
|
286
|
+
# @param fields fields to display
|
287
|
+
# @param base_query a query applied always
|
288
|
+
# @param default_query default query unless overriden by user
|
285
289
|
def result_list(resource_class_path, fields: nil, base_query: {}, default_query: {})
|
286
290
|
Aspera.assert_type(base_query, Hash)
|
287
291
|
Aspera.assert_type(default_query, Hash)
|
288
292
|
user_query = query_read_delete(default: default_query)
|
289
293
|
# caller may add specific modifications or checks
|
290
294
|
yield(user_query) if block_given?
|
291
|
-
return {type: :object_list, fields: fields}.merge(api_read_all(resource_class_path, base_query.merge(user_query)))
|
295
|
+
return {type: :object_list, fields: fields}.merge(api_read_all(resource_class_path, base_query.merge(user_query).compact))
|
292
296
|
end
|
293
297
|
|
294
298
|
def resolve_dropbox_name_default_ws_id(query)
|
@@ -411,8 +415,8 @@ module Aspera
|
|
411
415
|
when :operation then default_fields = nil
|
412
416
|
when :short_link then default_fields.push('short_url', 'data.url_token_data.purpose')
|
413
417
|
when :user then default_fields.push('name', 'email')
|
414
|
-
when :group_membership then default_fields.push(
|
415
|
-
when :workspace_membership then default_fields.push(
|
418
|
+
when :group_membership then default_fields.push('group_id', 'member_type', 'member_id')
|
419
|
+
when :workspace_membership then default_fields.push('workspace_id', 'member_type', 'member_id')
|
416
420
|
end
|
417
421
|
return result_list(resource_class_path, fields: default_fields, default_query: default_query)
|
418
422
|
when :show
|
@@ -801,6 +805,12 @@ module Aspera
|
|
801
805
|
else
|
802
806
|
ids_to_download = [ids_to_download] unless ids_to_download.is_a?(Array)
|
803
807
|
end
|
808
|
+
file_list =
|
809
|
+
begin
|
810
|
+
transfer.source_list.map{|i|{'source'=>i}}
|
811
|
+
rescue Cli::BadArgument
|
812
|
+
[{'source' => '.'}]
|
813
|
+
end
|
804
814
|
# list here
|
805
815
|
result_transfer = []
|
806
816
|
formatter.display_status("found #{ids_to_download.length} package(s).")
|
@@ -816,7 +826,7 @@ module Aspera
|
|
816
826
|
package_node_api.transfer_spec_gen4(
|
817
827
|
package_info['contents_file_id'],
|
818
828
|
Transfer::Spec::DIRECTION_RECEIVE,
|
819
|
-
{'paths'=>
|
829
|
+
{'paths'=> file_list}),
|
820
830
|
rest_token: package_node_api)
|
821
831
|
result_transfer.push({'package' => package_id, Main::STATUS_FIELD => statuses})
|
822
832
|
# update skip list only if all transfer sessions completed
|
@@ -837,14 +847,14 @@ module Aspera
|
|
837
847
|
resolve_dropbox_name_default_ws_id(query)
|
838
848
|
end
|
839
849
|
when :delete
|
840
|
-
return do_bulk_operation(command: package_command, descr: 'identifier', values:
|
850
|
+
return do_bulk_operation(command: package_command, descr: 'identifier', values: instance_identifier) do |id|
|
841
851
|
Aspera.assert_values(id.class, [String, Integer]){'identifier'}
|
842
852
|
aoc_api.delete("packages/#{id}")
|
843
853
|
end
|
844
854
|
when *Node::NODE4_READ_ACTIONS
|
845
855
|
package_id = instance_identifier
|
846
856
|
package_info = aoc_api.read("packages/#{package_id}")
|
847
|
-
return execute_nodegen4_command(package_command, package_info['node_id'], file_id: package_info['
|
857
|
+
return execute_nodegen4_command(package_command, package_info['node_id'], file_id: package_info['contents_file_id'], scope: Api::Node::SCOPE_USER)
|
848
858
|
end
|
849
859
|
when :files
|
850
860
|
command_repo = options.get_next_command([:short_link].concat(NODE4_EXT_COMMANDS))
|
@@ -9,7 +9,7 @@ require 'aspera/cli/formatter'
|
|
9
9
|
require 'aspera/cli/info'
|
10
10
|
require 'aspera/cli/transfer_progress'
|
11
11
|
require 'aspera/ascp/installation'
|
12
|
-
require 'aspera/
|
12
|
+
require 'aspera/products/trsdk'
|
13
13
|
require 'aspera/transfer/error_info'
|
14
14
|
require 'aspera/transfer/parameters'
|
15
15
|
require 'aspera/transfer/spec'
|
@@ -54,7 +54,7 @@ module Aspera
|
|
54
54
|
PERSISTENCY_FOLDER = 'persist_store'
|
55
55
|
ASPERA = 'aspera'
|
56
56
|
SERVER_COMMAND = 'server'
|
57
|
-
|
57
|
+
DIR_SDK = 'sdk'
|
58
58
|
CONNECT_WEB_URL = 'https://d3gcli72yxqn2z.cloudfront.net/connect'
|
59
59
|
CONNECT_VERSIONS = 'connectversions.js' # cspell: disable-line
|
60
60
|
DEMO_SERVER = 'demo'
|
@@ -213,7 +213,7 @@ module Aspera
|
|
213
213
|
options.declare(:ascp_path, 'Path to ascp', handler: {o: Ascp::Installation.instance, m: :ascp_path})
|
214
214
|
options.declare(:use_product, 'Use ascp from specified product', handler: {o: self, m: :option_use_product})
|
215
215
|
options.declare(:sdk_url, 'URL to get SDK', default: SpecialValues::DEF)
|
216
|
-
options.declare(:sdk_folder, 'SDK folder path', handler: {o:
|
216
|
+
options.declare(:sdk_folder, 'SDK folder path', handler: {o: Products::Trsdk, m: :sdk_directory})
|
217
217
|
options.declare(:progress_bar, 'Display progress bar', values: :bool, default: Environment.terminal?)
|
218
218
|
# email options
|
219
219
|
options.declare(:smtp, 'SMTP configuration', types: Hash)
|
@@ -232,22 +232,22 @@ module Aspera
|
|
232
232
|
options.parse_options!
|
233
233
|
@progress_bar = TransferProgress.new if options.get_option(:progress_bar)
|
234
234
|
# Check SDK folder is set or not, for compatibility, we check in two places
|
235
|
-
|
236
|
-
if
|
235
|
+
sdk_dir = Products::Trsdk.sdk_directory rescue nil
|
236
|
+
if sdk_dir.nil?
|
237
237
|
@sdk_default_location = true
|
238
238
|
Log.log.debug('SDK folder is not set, checking default')
|
239
239
|
# new location
|
240
|
-
|
241
|
-
Log.log.debug{"checking: #{
|
242
|
-
if !Dir.exist?(
|
243
|
-
Log.log.debug{"not exists: #{
|
240
|
+
sdk_dir = self.class.default_app_main_folder(app_name: DIR_SDK)
|
241
|
+
Log.log.debug{"checking: #{sdk_dir}"}
|
242
|
+
if !Dir.exist?(sdk_dir)
|
243
|
+
Log.log.debug{"not exists: #{sdk_dir}"}
|
244
244
|
# former location
|
245
|
-
former_sdk_folder = File.join(self.class.default_app_main_folder(app_name: Info::CMD_NAME),
|
245
|
+
former_sdk_folder = File.join(self.class.default_app_main_folder(app_name: Info::CMD_NAME), DIR_SDK)
|
246
246
|
Log.log.debug{"checking: #{former_sdk_folder}"}
|
247
|
-
|
247
|
+
sdk_dir = former_sdk_folder if Dir.exist?(former_sdk_folder)
|
248
248
|
end
|
249
|
-
Log.log.debug{"using: #{
|
250
|
-
|
249
|
+
Log.log.debug{"using: #{sdk_dir}"}
|
250
|
+
Products::Trsdk.sdk_directory = sdk_dir
|
251
251
|
end
|
252
252
|
pac_script = options.get_option(:fpac)
|
253
253
|
# create PAC executor
|
@@ -414,7 +414,7 @@ module Aspera
|
|
414
414
|
|
415
415
|
def periodic_check_newer_gem_version
|
416
416
|
# get verification period
|
417
|
-
delay_days = options.get_option(:version_check_days, mandatory: true)
|
417
|
+
delay_days = options.get_option(:version_check_days, mandatory: true).to_i
|
418
418
|
# check only if not zero day
|
419
419
|
return if delay_days.eql?(0)
|
420
420
|
# get last date from persistency
|
@@ -700,6 +700,7 @@ module Aspera
|
|
700
700
|
return execute_connect_action
|
701
701
|
when :use
|
702
702
|
ascp_path = options.get_next_argument('path to ascp')
|
703
|
+
Ascp::Installation.instance.ascp_path = ascp_path
|
703
704
|
formatter.display_status("ascp version: #{Ascp::Installation.instance.get_ascp_version(ascp_path)}")
|
704
705
|
set_global_default(:ascp_path, ascp_path)
|
705
706
|
return Main.result_nothing
|
@@ -713,13 +714,13 @@ module Aspera
|
|
713
714
|
# add keys
|
714
715
|
DataRepository::ELEMENTS.each_with_object(data){|i, h|h[i.to_s] = DataRepository.instance.item(i)}
|
715
716
|
# declare those as secrets
|
716
|
-
SecretHider::ADDITIONAL_KEYS_TO_HIDE.
|
717
|
+
SecretHider::ADDITIONAL_KEYS_TO_HIDE.concat(DataRepository::ELEMENTS.map(&:to_s))
|
717
718
|
return {type: :single_object, data: data}
|
718
719
|
when :products
|
719
720
|
command = options.get_next_command(%i[list use])
|
720
721
|
case command
|
721
722
|
when :list
|
722
|
-
return {type: :object_list, data: Ascp::
|
723
|
+
return {type: :object_list, data: Ascp::Installation.instance.installed_products, fields: %w[name app_root]}
|
723
724
|
when :use
|
724
725
|
default_product = options.get_next_argument('product name')
|
725
726
|
Ascp::Installation.instance.use_ascp_from_product(default_product)
|
@@ -728,7 +729,7 @@ module Aspera
|
|
728
729
|
end
|
729
730
|
when :install
|
730
731
|
# reset to default location, if older default was used
|
731
|
-
|
732
|
+
Products::Trsdk.sdk_directory = self.class.default_app_main_folder(app_name: DIR_SDK) if @sdk_default_location
|
732
733
|
n, v = Ascp::Installation.instance.install_sdk(url: options.get_option(:sdk_url, mandatory: true))
|
733
734
|
return Main.result_status("Installed #{n} version #{v}")
|
734
735
|
when :spec
|
@@ -856,7 +857,7 @@ module Aspera
|
|
856
857
|
remote_certificate
|
857
858
|
gem
|
858
859
|
plugins
|
859
|
-
|
860
|
+
tokens
|
860
861
|
echo
|
861
862
|
wizard
|
862
863
|
detect
|
@@ -912,9 +913,18 @@ module Aspera
|
|
912
913
|
end
|
913
914
|
when :echo # display the content of a value given on command line
|
914
915
|
return Formatter.auto_type(options.get_next_argument('value', validation: nil))
|
915
|
-
when :
|
916
|
-
|
917
|
-
|
916
|
+
when :tokens
|
917
|
+
require 'aspera/api/node'
|
918
|
+
case options.get_next_command(%i{flush list show})
|
919
|
+
when :flush
|
920
|
+
return {type: :value_list, data: OAuth::Factory.instance.flush_tokens, name: 'file'}
|
921
|
+
when :list
|
922
|
+
return {type: :object_list, data: OAuth::Factory.instance.persisted_tokens}
|
923
|
+
when :show
|
924
|
+
data = OAuth::Factory.instance.get_token_info(instance_identifier)
|
925
|
+
raise Cli::Error, 'No such identifier' if data.nil?
|
926
|
+
return {type: :single_object, data: data}
|
927
|
+
end
|
918
928
|
when :plugins
|
919
929
|
case options.get_next_command(%i[list create])
|
920
930
|
when :list
|
@@ -305,7 +305,7 @@ module Aspera
|
|
305
305
|
# authenticated user
|
306
306
|
delivery_info['sources'] ||= [{'paths' => []}]
|
307
307
|
first_source = delivery_info['sources'].first
|
308
|
-
first_source['paths'].
|
308
|
+
first_source['paths'].concat(transfer.source_list)
|
309
309
|
source_id = instance_identifier(as_option: :remote_source) do |field, value|
|
310
310
|
Aspera.assert(field.eql?('name'), exception_class: Cli::BadArgument){'only name as selector, or give id'}
|
311
311
|
source_list = api_v3.read('source_shares')['items']
|
@@ -253,9 +253,10 @@ module Aspera
|
|
253
253
|
# @param query [Hash,nil] additional query parameters
|
254
254
|
# @param real_path [String] real path if it's n ot just the type
|
255
255
|
# @param item_list_key [String] key in the result to get the list of items
|
256
|
-
def list_entities(type:, real_path: nil, item_list_key: nil, query:
|
256
|
+
def list_entities(type:, real_path: nil, item_list_key: nil, query: nil)
|
257
257
|
Log.log.trace1{"list_entities t=#{type} p=#{real_path} k=#{item_list_key} q=#{query}"}
|
258
258
|
type = type.to_s if type.is_a?(Symbol)
|
259
|
+
query = {} if query.nil?
|
259
260
|
Aspera.assert_type(type, String)
|
260
261
|
Aspera.assert_type(query, Hash)
|
261
262
|
item_list_key = type if item_list_key.nil?
|
@@ -555,6 +556,7 @@ module Aspera
|
|
555
556
|
id_as_arg = 'type'
|
556
557
|
when :accounts
|
557
558
|
display_fields = Formatter.all_but('user_profile_data_attributes')
|
559
|
+
available_commands.push(:reset_password)
|
558
560
|
when :oauth_clients
|
559
561
|
display_fields = Formatter.all_but('public_key')
|
560
562
|
adm_api = Rest.new(**@api_v5.params.merge(base_url: "#{@faspex5_api_base_url}/#{PATH_AUTH}"))
|
@@ -642,7 +644,12 @@ module Aspera
|
|
642
644
|
value: value,
|
643
645
|
query: {type: Rest.array_params(%w{local_user saml_user self_registered_user external_user})})['id']
|
644
646
|
end
|
647
|
+
when :reset_password
|
648
|
+
contact_id = instance_identifier { |field, value| lookup_entity_by_field(type: res_type.to_s, field: field, value: value, query: res_id_query)['id']}
|
649
|
+
adm_api.create("#{res_type}/#{contact_id}/reset_password", {})
|
650
|
+
return Main.result_status('password reset, user shall check email')
|
645
651
|
end
|
652
|
+
Aspera.error_unreachable_line
|
646
653
|
end
|
647
654
|
|
648
655
|
def execute_admin
|
@@ -662,9 +669,10 @@ module Aspera
|
|
662
669
|
event_type = options.get_next_command(%i[application webhook])
|
663
670
|
case event_type
|
664
671
|
when :application
|
665
|
-
return {type: :object_list, data: list_entities(type: 'application_events'
|
672
|
+
return {type: :object_list, data: list_entities(type: 'application_events', query: query_read_delete),
|
673
|
+
fields: %w[event_type created_at application user.name]}
|
666
674
|
when :webhook
|
667
|
-
return {type: :object_list, data: list_entities(type: 'all_webhooks_events', item_list_key: 'events')}
|
675
|
+
return {type: :object_list, data: list_entities(type: 'all_webhooks_events', query: query_read_delete, item_list_key: 'events')}
|
668
676
|
end
|
669
677
|
when :configuration
|
670
678
|
conf_path = 'configuration'
|
@@ -131,6 +131,8 @@ module Aspera
|
|
131
131
|
COMMANDS_SHARES = (BASE_ACTIONS - %i[search]).freeze
|
132
132
|
COMMANDS_FASPEX = COMMON_ACTIONS
|
133
133
|
|
134
|
+
GEN4_LS_FIELDS = %w[name type recursive_size size modified_time access_level].freeze
|
135
|
+
|
134
136
|
def initialize(api: nil, **env)
|
135
137
|
super(**env, basic_options: api.nil?)
|
136
138
|
Node.declare_options(options) if api.nil?
|
@@ -484,22 +486,15 @@ module Aspera
|
|
484
486
|
when :browse
|
485
487
|
apifid = apifid_from_next_arg(top_file_id)
|
486
488
|
file_info = apifid[:api].read_with_cache("files/#{apifid[:file_id]}")
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
subpath: "files/#{apifid[:file_id]}/files",
|
491
|
-
headers: Api::Node.cache_control_headers,
|
492
|
-
query: query_read_delete)
|
493
|
-
items = result[:data]
|
494
|
-
formatter.display_item_count(result[:data].length, result[:http]['X-Total-Count'])
|
495
|
-
else
|
496
|
-
items = [file_info]
|
489
|
+
unless file_info['type'].eql?('folder')
|
490
|
+
# a single file
|
491
|
+
return {type: :object_list, data: [file_info], fields: GEN4_LS_FIELDS}
|
497
492
|
end
|
498
|
-
return {type: :object_list, data:
|
493
|
+
return {type: :object_list, data: apifid[:api].list_files(apifid[:file_id]), fields: GEN4_LS_FIELDS}
|
499
494
|
when :find
|
500
495
|
apifid = apifid_from_next_arg(top_file_id)
|
501
|
-
|
502
|
-
return {type: :object_list, data: @api_node.find_files(apifid[:file_id],
|
496
|
+
find_lambda = Api::Node.file_matcher_from_argument(options)
|
497
|
+
return {type: :object_list, data: @api_node.find_files(apifid[:file_id], find_lambda), fields: ['path']}
|
503
498
|
when :mkdir
|
504
499
|
containing_folder_path = options.get_next_argument('path').split(Api::Node::PATH_SEPARATOR)
|
505
500
|
new_folder = containing_folder_path.pop
|
@@ -608,12 +603,12 @@ module Aspera
|
|
608
603
|
command_perm = options.get_next_command(%i[list create delete])
|
609
604
|
case command_perm
|
610
605
|
when :list
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
items = apifid[:api].read('permissions',
|
606
|
+
list_query = query_read_delete(default: {'include' => Rest.array_params(%w[access_level permission_count])})
|
607
|
+
# specify file to get permissions for unless not specified
|
608
|
+
list_query['file_id'] = apifid[:file_id] unless apifid[:file_id].to_s.empty?
|
609
|
+
list_query['inherited'] = false if list_query.key?('file_id') && !list_query.key?('inherited')
|
610
|
+
# NOTE: supports per_page and page and header X-Total-Count
|
611
|
+
items = apifid[:api].read('permissions', list_query)
|
617
612
|
return {type: :object_list, data: items}
|
618
613
|
when :delete
|
619
614
|
return do_bulk_operation(command: command_perm, descr: 'identifier', values: :identifier) do |one_id|
|
@@ -802,42 +797,53 @@ module Aspera
|
|
802
797
|
end
|
803
798
|
case command
|
804
799
|
when :list
|
800
|
+
transfer_filter = query_read_delete(default: {})
|
801
|
+
last_iteration_token = nil
|
805
802
|
iteration_persistency = nil
|
806
|
-
iteration_data = []
|
807
803
|
if options.get_option(:once_only, mandatory: true)
|
808
804
|
iteration_persistency = PersistencyActionOnce.new(
|
809
805
|
manager: persistency,
|
810
|
-
data:
|
806
|
+
data: [],
|
811
807
|
id: IdGenerator.from_list([
|
812
808
|
'node_transfers',
|
813
809
|
options.get_option(:url, mandatory: true),
|
814
810
|
options.get_option(:username, mandatory: true)
|
815
811
|
]))
|
812
|
+
if transfer_filter.delete('reset')
|
813
|
+
iteration_persistency.data.clear
|
814
|
+
iteration_persistency.save
|
815
|
+
return Main.result_status('Persistency reset')
|
816
|
+
end
|
817
|
+
last_iteration_token = iteration_persistency.data.first
|
816
818
|
end
|
817
|
-
|
818
|
-
if transfer_filter.delete('reset')
|
819
|
-
iteration_data.clear
|
820
|
-
iteration_persistency&.save
|
821
|
-
return Main.result_status('Persistency reset')
|
822
|
-
end
|
819
|
+
raise 'reset only with once_only' if transfer_filter.key?('reset') && iteration_persistency.nil?
|
823
820
|
max_items = transfer_filter.delete(MAX_ITEMS)
|
824
|
-
transfer_filter['iteration_token'] = iteration_persistency.data[0] unless iteration_data.empty?
|
825
821
|
transfers_data = []
|
826
822
|
loop do
|
823
|
+
transfer_filter['iteration_token'] = last_iteration_token unless last_iteration_token.nil?
|
827
824
|
result = @api_node.call(operation: 'GET', subpath: res_class_path, query: transfer_filter)
|
828
|
-
|
829
|
-
|
830
|
-
|
825
|
+
# no data
|
826
|
+
break if result[:data].empty?
|
827
|
+
# get next iteration token from link
|
828
|
+
next_iteration_token = nil
|
829
|
+
link_info = result[:http]['Link']
|
830
|
+
unless link_info.nil?
|
831
|
+
m = link_info.match(/<([^>]+)>/)
|
832
|
+
raise "Cannot parse iteration in Link: #{link_info}" if m.nil?
|
833
|
+
next_iteration_token = CGI.parse(URI.parse(m[1]).query)['iteration_token']&.first
|
834
|
+
end
|
835
|
+
# same as last iteration: stop
|
836
|
+
break if next_iteration_token&.eql?(last_iteration_token)
|
837
|
+
last_iteration_token = next_iteration_token
|
838
|
+
transfers_data.concat(result[:data])
|
839
|
+
if max_items&.<=(transfers_data.length)
|
840
|
+
# if !max_items.nil? && (transfers_data.length >= max_items)
|
831
841
|
transfers_data = transfers_data.slice(0, max_items)
|
832
842
|
break
|
833
843
|
end
|
834
|
-
|
835
|
-
break if iteration_persistency.nil? || data.empty? || link_info.nil?
|
836
|
-
m = link_info.match(/<([^>]+)>/)
|
837
|
-
raise "Problem with iteration: #{link_info}" if m.nil?
|
838
|
-
iteration_token = CGI.parse(URI.parse(m[1]).query)['iteration_token']&.first
|
839
|
-
iteration_data[0] = transfer_filter['iteration_token'] = iteration_token
|
844
|
+
break if last_iteration_token.nil?
|
840
845
|
end
|
846
|
+
iteration_persistency&.data&.[]=(0, last_iteration_token)
|
841
847
|
iteration_persistency&.save
|
842
848
|
return {
|
843
849
|
type: :object_list,
|
@@ -1019,7 +1025,7 @@ module Aspera
|
|
1019
1025
|
raise 'Missing key: url' unless parameters.key?(:url)
|
1020
1026
|
uri = URI.parse(parameters[:url])
|
1021
1027
|
server = WebServerSimple.new(uri, certificate: parameters[:certificate])
|
1022
|
-
server.mount(uri.path, NodeSimulatorServlet, parameters[:credentials],
|
1028
|
+
server.mount(uri.path, NodeSimulatorServlet, parameters[:credentials], NodeSimulator.new)
|
1023
1029
|
server.start
|
1024
1030
|
return Main.result_status('Simulator terminated')
|
1025
1031
|
end
|
data/lib/aspera/cli/version.rb
CHANGED
@@ -77,7 +77,7 @@ module Aspera
|
|
77
77
|
@param_hash.each_pair{|key, val|Log.log.warn{"unrecognized parameter: #{key} = \"#{val}\""} if !@used_param_names.include?(key)}
|
78
78
|
# set result
|
79
79
|
env_args[:env].merge!(@result[:env])
|
80
|
-
env_args[:args].
|
80
|
+
env_args[:args].concat(@result[:args])
|
81
81
|
return nil
|
82
82
|
end
|
83
83
|
|
data/lib/aspera/environment.rb
CHANGED
@@ -46,8 +46,7 @@ module Aspera
|
|
46
46
|
return OS_LINUX
|
47
47
|
when /aix/
|
48
48
|
return OS_AIX
|
49
|
-
else
|
50
|
-
raise "Unknown OS: #{RbConfig::CONFIG['host_os']}"
|
49
|
+
else Aspera.error_unexpected_value(RbConfig::CONFIG['host_os']){'host_os'}
|
51
50
|
end
|
52
51
|
end
|
53
52
|
|
@@ -62,8 +61,8 @@ module Aspera
|
|
62
61
|
return CPU_S390
|
63
62
|
when /arm/, /aarch64/
|
64
63
|
return CPU_ARM64
|
64
|
+
else Aspera.error_unexpected_value(RbConfig::CONFIG['host_cpu']){'host_cpu'}
|
65
65
|
end
|
66
|
-
raise "Unknown CPU: #{RbConfig::CONFIG['host_cpu']}"
|
67
66
|
end
|
68
67
|
|
69
68
|
# normalized architecture name
|
@@ -73,9 +72,9 @@ module Aspera
|
|
73
72
|
end
|
74
73
|
|
75
74
|
# executable file extension for current OS
|
76
|
-
def
|
77
|
-
return
|
78
|
-
return
|
75
|
+
def exe_file(name='')
|
76
|
+
return "#{name}.exe" if os.eql?(OS_WINDOWS)
|
77
|
+
return name
|
79
78
|
end
|
80
79
|
|
81
80
|
# on Windows, the env var %USERPROFILE% provides the path to user's home more reliably than %HOMEDRIVE%%HOMEPATH%
|