aspera-cli 4.25.4 → 4.26.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +21 -6
- data/CONTRIBUTING.md +28 -22
- data/README.md +9 -7
- data/lib/aspera/agent/direct.rb +10 -8
- data/lib/aspera/agent/factory.rb +3 -3
- data/lib/aspera/agent/node.rb +1 -1
- data/lib/aspera/api/alee.rb +1 -0
- data/lib/aspera/api/aoc.rb +8 -4
- data/lib/aspera/api/ats.rb +1 -1
- data/lib/aspera/api/cos_node.rb +1 -0
- data/lib/aspera/api/faspex.rb +5 -1
- data/lib/aspera/api/httpgw.rb +2 -0
- data/lib/aspera/api/node.rb +3 -2
- data/lib/aspera/ascp/installation.rb +9 -10
- data/lib/aspera/cli/error.rb +8 -0
- data/lib/aspera/cli/info.rb +2 -1
- data/lib/aspera/cli/main.rb +30 -12
- data/lib/aspera/cli/manager.rb +31 -28
- data/lib/aspera/cli/plugins/aoc.rb +2 -2
- data/lib/aspera/cli/plugins/base.rb +2 -79
- data/lib/aspera/cli/plugins/faspex.rb +1 -1
- data/lib/aspera/cli/plugins/faspex5.rb +28 -40
- data/lib/aspera/cli/plugins/node.rb +2 -4
- data/lib/aspera/cli/plugins/shares.rb +4 -2
- data/lib/aspera/cli/transfer_agent.rb +3 -0
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/dot_container.rb +10 -10
- data/lib/aspera/log.rb +1 -1
- data/lib/aspera/markdown.rb +1 -1
- data/lib/aspera/persistency_folder.rb +1 -1
- data/lib/aspera/rest.rb +3 -31
- data/lib/aspera/rest_list.rb +116 -0
- data/lib/aspera/sync/operations.rb +1 -1
- data/lib/aspera/transfer/parameters.rb +8 -8
- data/lib/aspera/yaml.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +4 -3
- metadata.gz.sig +0 -0
data/lib/aspera/cli/main.rb
CHANGED
|
@@ -12,18 +12,34 @@ require 'aspera/cli/hints'
|
|
|
12
12
|
require 'aspera/secret_hider'
|
|
13
13
|
require 'aspera/log'
|
|
14
14
|
require 'aspera/assert'
|
|
15
|
+
require 'net/ssh/errors'
|
|
16
|
+
require 'openssl'
|
|
15
17
|
|
|
16
18
|
module Aspera
|
|
17
19
|
module Cli
|
|
18
20
|
# Global objects shared with plugins
|
|
19
21
|
class Context
|
|
22
|
+
# @!attribute [rw] options
|
|
23
|
+
# @return [Manager] the command line options manager
|
|
24
|
+
# @!attribute [rw] transfer
|
|
25
|
+
# @return [TransferAgent] the transfer agent, used by transfer plugins
|
|
26
|
+
# @!attribute [rw] config
|
|
27
|
+
# @return [Plugins::Config] the configuration plugin, used by plugins to get configuration values and presets
|
|
28
|
+
# @!attribute [rw] formatter
|
|
29
|
+
# @return [Formatter] the formatter, used by plugins to display results and messages
|
|
30
|
+
# @!attribute [rw] persistency
|
|
31
|
+
# @return [Object] # whatever the type is
|
|
32
|
+
# @!attribute [rw] man_header
|
|
33
|
+
# @return [Boolean] whether to display the manual header in plugin help
|
|
20
34
|
MEMBERS = %i[options transfer config formatter persistency man_header].freeze
|
|
21
35
|
attr_accessor(*MEMBERS)
|
|
22
36
|
|
|
37
|
+
# Initialize all members to nil, so that they are defined and can be validated later
|
|
23
38
|
def initialize
|
|
24
|
-
|
|
39
|
+
MEMBERS.each{ |i| instance_variable_set(:"@#{i}", nil)}
|
|
25
40
|
end
|
|
26
41
|
|
|
42
|
+
# Validate that all members are set, raise exception if not
|
|
27
43
|
def validate
|
|
28
44
|
MEMBERS.each do |i|
|
|
29
45
|
Aspera.assert(instance_variable_defined?(:"@#{i}"))
|
|
@@ -35,7 +51,7 @@ module Aspera
|
|
|
35
51
|
transfer.eql?(:only_manual)
|
|
36
52
|
end
|
|
37
53
|
|
|
38
|
-
def only_manual
|
|
54
|
+
def only_manual!
|
|
39
55
|
@transfer = :only_manual
|
|
40
56
|
end
|
|
41
57
|
end
|
|
@@ -89,13 +105,15 @@ module Aspera
|
|
|
89
105
|
status_table.each do |item|
|
|
90
106
|
worst = TransferAgent.session_status(item[STATUS_FIELD])
|
|
91
107
|
global_status = worst unless worst.eql?(:success)
|
|
92
|
-
item[STATUS_FIELD] = item[STATUS_FIELD].
|
|
108
|
+
item[STATUS_FIELD] = item[STATUS_FIELD].join(',')
|
|
93
109
|
end
|
|
94
110
|
raise global_status unless global_status.eql?(:success)
|
|
95
111
|
return result_object_list(status_table)
|
|
96
112
|
end
|
|
97
113
|
|
|
98
114
|
# Display image for that URL or directly blob
|
|
115
|
+
#
|
|
116
|
+
# @param url_or_blob [String] URL or blob to display as image
|
|
99
117
|
def result_image(url_or_blob)
|
|
100
118
|
return {type: :image, data: url_or_blob}
|
|
101
119
|
end
|
|
@@ -111,6 +129,9 @@ module Aspera
|
|
|
111
129
|
end
|
|
112
130
|
|
|
113
131
|
# A list of values
|
|
132
|
+
#
|
|
133
|
+
# @param data [Array] The list of values
|
|
134
|
+
# @param name [String] The name of the list (used for display)
|
|
114
135
|
def result_value_list(data, name: 'id')
|
|
115
136
|
Aspera.assert_type(data, Array)
|
|
116
137
|
Aspera.assert_type(name, String)
|
|
@@ -155,7 +176,9 @@ module Aspera
|
|
|
155
176
|
execute_command = true
|
|
156
177
|
# Catch exceptions
|
|
157
178
|
begin
|
|
158
|
-
|
|
179
|
+
init_agents_and_options
|
|
180
|
+
# Find plugins, shall be after parse! ?
|
|
181
|
+
Plugins::Factory.instance.add_plugins_from_lookup_folders
|
|
159
182
|
# Help requested without command ? (plugins must be known here)
|
|
160
183
|
show_usage if @option_help && @context.options.command_or_arg_empty?
|
|
161
184
|
generate_bash_completion if @bash_completion
|
|
@@ -253,17 +276,11 @@ module Aspera
|
|
|
253
276
|
return
|
|
254
277
|
end
|
|
255
278
|
|
|
256
|
-
def init_agents_options_plugins
|
|
257
|
-
init_agents_and_options
|
|
258
|
-
# Find plugins, shall be after parse! ?
|
|
259
|
-
Plugins::Factory.instance.add_plugins_from_lookup_folders
|
|
260
|
-
end
|
|
261
|
-
|
|
262
279
|
def show_usage(all: true, exit: true)
|
|
263
280
|
# Display main plugin options (+config)
|
|
264
281
|
@context.formatter.display_message(:error, @context.options.parser)
|
|
265
282
|
if all
|
|
266
|
-
@context.only_manual
|
|
283
|
+
@context.only_manual!
|
|
267
284
|
# List plugins that have a "require" field, i.e. all but main plugin
|
|
268
285
|
Plugins::Factory.instance.plugin_list.each do |plugin_name_sym|
|
|
269
286
|
# Config was already included in the global options
|
|
@@ -283,6 +300,7 @@ module Aspera
|
|
|
283
300
|
|
|
284
301
|
# This can throw exception if there is a problem with the environment, needs to be caught by execute method
|
|
285
302
|
def init_agents_and_options
|
|
303
|
+
@context.man_header = true
|
|
286
304
|
# Create formatter, in case there is an exception, it is used to display.
|
|
287
305
|
@context.formatter = Formatter.new
|
|
288
306
|
# Create command line manager with arguments
|
|
@@ -336,7 +354,7 @@ module Aspera
|
|
|
336
354
|
OPTIONS
|
|
337
355
|
#{t}Options begin with a '-' (minus), and value is provided on command line.
|
|
338
356
|
#{t}Special values are supported beginning with special prefix @pfx:, where pfx is one of:
|
|
339
|
-
#{t}#{ExtendedValue.instance.modifiers.
|
|
357
|
+
#{t}#{ExtendedValue.instance.modifiers.join(', ')}
|
|
340
358
|
#{t}Dates format is 'DD-MM-YY HH:MM:SS', or 'now' or '-<num>h'
|
|
341
359
|
|
|
342
360
|
ARGS
|
data/lib/aspera/cli/manager.rb
CHANGED
|
@@ -194,7 +194,9 @@ module Aspera
|
|
|
194
194
|
[error_msg, 'Use:'].concat(accept_list.map{ |c| "- #{c}"}.sort).join("\n")
|
|
195
195
|
end
|
|
196
196
|
|
|
197
|
-
#
|
|
197
|
+
# Change option name with dash to name with underscore
|
|
198
|
+
# @param name [String] option name
|
|
199
|
+
# @return [String]
|
|
198
200
|
def option_line_to_name(name)
|
|
199
201
|
return name.gsub(OPTION_SEP_LINE, OPTION_SEP_SYMBOL)
|
|
200
202
|
end
|
|
@@ -211,7 +213,7 @@ module Aspera
|
|
|
211
213
|
def initialize(program_name, argv = nil)
|
|
212
214
|
# command line values *not* starting with '-'
|
|
213
215
|
@unprocessed_cmd_line_arguments = []
|
|
214
|
-
# command line values starting with '-'
|
|
216
|
+
# command line values starting with at least one '-'
|
|
215
217
|
@unprocessed_cmd_line_options = []
|
|
216
218
|
# a copy of all initial options
|
|
217
219
|
@initial_cli_options = []
|
|
@@ -330,7 +332,7 @@ module Aspera
|
|
|
330
332
|
|
|
331
333
|
# @param descr [String] description for help
|
|
332
334
|
# @param mandatory [Boolean] if true, raise error if option not set
|
|
333
|
-
# @param multiple [Boolean] if true, return remaining arguments (Array)
|
|
335
|
+
# @param multiple [Boolean] if true, return remaining arguments (Array) until END
|
|
334
336
|
# @param accept_list [Array, NilClass] list of allowed values (Symbol)
|
|
335
337
|
# @param validation [Class, Array, NilClass] Accepted value type(s) or list of Symbols
|
|
336
338
|
# @param aliases [Hash] map of aliases: key = alias, value = real value
|
|
@@ -466,21 +468,17 @@ module Aspera
|
|
|
466
468
|
# @return [Hash] options as taken from config file and command line just before command execution
|
|
467
469
|
def unprocessed_options_with_value
|
|
468
470
|
result = {}
|
|
469
|
-
@initial_cli_options.each do |
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
@unprocessed_cmd_line_options.delete(option_value)
|
|
481
|
-
else
|
|
482
|
-
raise Cli::BadArgument, "wrong option format: #{option_value}"
|
|
483
|
-
end
|
|
471
|
+
@initial_cli_options.each do |option_argument|
|
|
472
|
+
# ignore short options
|
|
473
|
+
next unless option_argument.start_with?(OPTION_PREFIX)
|
|
474
|
+
name, value = option_argument[OPTION_PREFIX.length..-1].split(OPTION_VALUE_SEPARATOR, 2)
|
|
475
|
+
# ignore options without value
|
|
476
|
+
next if value.nil?
|
|
477
|
+
Log.log.debug{"option #{name}=#{value}"}
|
|
478
|
+
path = name.split(DotContainer::SEPARATOR)
|
|
479
|
+
path[0] = self.class.option_line_to_name(path[0])
|
|
480
|
+
DotContainer.dotted_to_container(path, smart_convert(value), result)
|
|
481
|
+
@unprocessed_cmd_line_options.delete(option_argument)
|
|
484
482
|
end
|
|
485
483
|
return result
|
|
486
484
|
end
|
|
@@ -516,20 +514,25 @@ module Aspera
|
|
|
516
514
|
rescue OptionParser::InvalidOption => e
|
|
517
515
|
Log.log.trace1{"InvalidOption #{e}".red}
|
|
518
516
|
# An option like --a.b.c=d does: a={"b":{"c":ext_val(d)}}
|
|
519
|
-
if
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
517
|
+
if e.args.first.start_with?(OPTION_PREFIX)
|
|
518
|
+
name, value = e.args.first[OPTION_PREFIX.length..-1].split(OPTION_VALUE_SEPARATOR, 2)
|
|
519
|
+
if !value.nil?
|
|
520
|
+
path = name.split(DotContainer::SEPARATOR)
|
|
521
|
+
option_sym = self.class.option_line_to_name(path.shift)
|
|
522
|
+
if @declared_options.key?(option_sym)
|
|
523
|
+
# it's a known option, so let's process it
|
|
524
|
+
set_option(option_sym, DotContainer.dotted_to_container(path, smart_convert(value), get_option(option_sym)), where: 'dotted')
|
|
525
|
+
# resume to next
|
|
526
|
+
retry
|
|
527
|
+
end
|
|
525
528
|
end
|
|
526
529
|
end
|
|
527
|
-
#
|
|
530
|
+
# Save for later processing
|
|
528
531
|
unknown_options.push(e.args.first)
|
|
529
532
|
retry
|
|
530
533
|
end
|
|
531
534
|
Log.log.trace1{"remains: #{unknown_options}"}
|
|
532
|
-
#
|
|
535
|
+
# Set unprocessed options for next time
|
|
533
536
|
@unprocessed_cmd_line_options = unknown_options
|
|
534
537
|
end
|
|
535
538
|
|
|
@@ -596,9 +599,9 @@ module Aspera
|
|
|
596
599
|
ExtendedValue.assert_no_value(arg, :p)
|
|
597
600
|
result = nil
|
|
598
601
|
get_next_argument(:args, multiple: true).each do |arg|
|
|
599
|
-
Aspera.assert(arg.include?(OPTION_VALUE_SEPARATOR)){"Positional argument: #{arg} does not
|
|
602
|
+
Aspera.assert(arg.include?(OPTION_VALUE_SEPARATOR)){"Positional argument: #{arg} does not include #{OPTION_VALUE_SEPARATOR}"}
|
|
600
603
|
path, value = arg.split(OPTION_VALUE_SEPARATOR, 2)
|
|
601
|
-
result = DotContainer.dotted_to_container(path, smart_convert(value), result)
|
|
604
|
+
result = DotContainer.dotted_to_container(path.split(DotContainer::SEPARATOR), smart_convert(value), result)
|
|
602
605
|
end
|
|
603
606
|
result
|
|
604
607
|
end
|
|
@@ -744,7 +744,7 @@ module Aspera
|
|
|
744
744
|
# Short link entity: `short_links` have:
|
|
745
745
|
# - a numerical id, e.g. `764412`
|
|
746
746
|
# - a resource type, e.g. `UrlToken`
|
|
747
|
-
# - a
|
|
747
|
+
# - a resource id, e.g. `scQ7uXPbvQ`
|
|
748
748
|
# - a short URL path, e.g. `dxyRpT9`
|
|
749
749
|
# @param shared_data [Hash] Information for shared data: dropbox_id+name or file_id+node_id
|
|
750
750
|
# @param &perm_block [Proc] Optional: create/modify/delete permissions on node
|
|
@@ -887,7 +887,7 @@ module Aspera
|
|
|
887
887
|
|
|
888
888
|
def reject_packages_from_persistency(all_packages, skip_ids_persistency)
|
|
889
889
|
return if skip_ids_persistency.nil?
|
|
890
|
-
skip_package = skip_ids_persistency.data.
|
|
890
|
+
skip_package = skip_ids_persistency.data.to_h{ |i| [i, true]}
|
|
891
891
|
all_packages.reject!{ |pkg| skip_package[pkg['id']]}
|
|
892
892
|
end
|
|
893
893
|
|
|
@@ -190,7 +190,7 @@ module Aspera
|
|
|
190
190
|
return Main.result_single_object(api.read(one_res_path), fields: display_fields)
|
|
191
191
|
when :list
|
|
192
192
|
if tclo
|
|
193
|
-
data, total = list_entities_limit_offset_total_count(
|
|
193
|
+
data, total = api.list_entities_limit_offset_total_count(entity:, items_key: items_key, query: query_read_delete(default: list_query))
|
|
194
194
|
return Main.result_object_list(data, total: total, fields: display_fields)
|
|
195
195
|
end
|
|
196
196
|
data, http = api.read(entity, query_read_delete, ret: :both)
|
|
@@ -259,86 +259,9 @@ module Aspera
|
|
|
259
259
|
return value
|
|
260
260
|
end
|
|
261
261
|
|
|
262
|
-
# Get a (full or partial) list of all entities of a given type with query: offset/limit
|
|
263
|
-
# @param api [Rest] API object
|
|
264
|
-
# @param entity [String,Symbol] API endpoint of entity to list
|
|
265
|
-
# @param items_key [String] Key in the result to get the list of items (Default: same as `entity`)
|
|
266
|
-
# @param query [Hash,nil] Additional query parameters
|
|
267
|
-
# @return [Array<(Array<Hash>, Integer)>] items, total_count
|
|
268
|
-
def list_entities_limit_offset_total_count(
|
|
269
|
-
api:,
|
|
270
|
-
entity:,
|
|
271
|
-
items_key: nil,
|
|
272
|
-
query: nil
|
|
273
|
-
)
|
|
274
|
-
entity = entity.to_s if entity.is_a?(Symbol)
|
|
275
|
-
items_key = entity.split('/').last if items_key.nil?
|
|
276
|
-
query = {} if query.nil?
|
|
277
|
-
Aspera.assert_type(entity, String)
|
|
278
|
-
Aspera.assert_type(items_key, String)
|
|
279
|
-
Aspera.assert_type(query, Hash)
|
|
280
|
-
Log.log.debug{"list_entities t=#{entity} k=#{items_key} q=#{query}"}
|
|
281
|
-
result = []
|
|
282
|
-
offset = 0
|
|
283
|
-
max_items = query.delete(MAX_ITEMS)
|
|
284
|
-
remain_pages = query.delete(MAX_PAGES)
|
|
285
|
-
# Merge default parameters, by default 100 per page
|
|
286
|
-
query = {'limit'=> PER_PAGE_DEFAULT}.merge(query)
|
|
287
|
-
total_count = nil
|
|
288
|
-
loop do
|
|
289
|
-
query['offset'] = offset
|
|
290
|
-
page_result = api.read(entity, query)
|
|
291
|
-
Aspera.assert_type(page_result[items_key], Array)
|
|
292
|
-
result.concat(page_result[items_key])
|
|
293
|
-
# Reach the limit set by user ?
|
|
294
|
-
if !max_items.nil? && (result.length >= max_items)
|
|
295
|
-
result = result.slice(0, max_items)
|
|
296
|
-
break
|
|
297
|
-
end
|
|
298
|
-
total_count ||= page_result['total_count']
|
|
299
|
-
break if result.length >= total_count
|
|
300
|
-
remain_pages -= 1 unless remain_pages.nil?
|
|
301
|
-
break if remain_pages == 0
|
|
302
|
-
offset += page_result[items_key].length
|
|
303
|
-
RestParameters.instance.spinner_cb.call("#{result.length} / #{total_count || '?'}")
|
|
304
|
-
end
|
|
305
|
-
RestParameters.instance.spinner_cb.call(action: :success)
|
|
306
|
-
return result, total_count
|
|
307
|
-
end
|
|
308
|
-
|
|
309
|
-
# Lookup an entity id from its name.
|
|
310
|
-
# Uses query `q` if `query` is `:default` and `field` is `name`.
|
|
311
|
-
# @param entity [String] Type of entity to lookup, by default it is the path, and it is also the field name in result
|
|
312
|
-
# @param value [String] Value to lookup
|
|
313
|
-
# @param field [String] Field to match, by default it is `'name'`
|
|
314
|
-
# @param items_key [String] Key in the result to get the list of items (override entity)
|
|
315
|
-
# @param query [Hash] Additional query parameters (Default: `:default`)
|
|
316
|
-
def lookup_entity_by_field(api:, entity:, value:, field: 'name', items_key: nil, query: :default)
|
|
317
|
-
if query.eql?(:default)
|
|
318
|
-
Aspera.assert(field.eql?('name')){'Default query is on name only'}
|
|
319
|
-
query = {'q'=> value}
|
|
320
|
-
end
|
|
321
|
-
lookup_entity_generic(entity: entity, field: field, value: value){list_entities_limit_offset_total_count(api: api, entity: entity, items_key: items_key, query: query).first}
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
# Lookup entity by field and value. Extract single result from list of result returned by block.
|
|
325
|
-
# @param entity [String] Type of entity to lookup, by default it is the path, and it is also the field name in result
|
|
326
|
-
# @param value [String] Value to lookup
|
|
327
|
-
# @param field [String] Field to match, by default it is `'name'`
|
|
328
|
-
# @param block [Proc] Get list of entity matching query.
|
|
329
|
-
def lookup_entity_generic(entity:, value:, field: 'name', &block)
|
|
330
|
-
Aspera.assert(block_given?)
|
|
331
|
-
found = yield
|
|
332
|
-
Aspera.assert_array_all(found, Hash)
|
|
333
|
-
found = found.select{ |i| i[field].eql?(value)}
|
|
334
|
-
return found.first if found.length.eql?(1)
|
|
335
|
-
raise Cli::BadIdentifier.new(entity, value, field: field, count: found.length)
|
|
336
|
-
end
|
|
337
|
-
|
|
338
|
-
PER_PAGE_DEFAULT = 1000
|
|
339
262
|
# Percent selector: select by this field for this value
|
|
340
263
|
REGEX_LOOKUP_ID_BY_FIELD = /^%([^:]+):(.*)$/
|
|
341
|
-
private_constant :
|
|
264
|
+
private_constant :REGEX_LOOKUP_ID_BY_FIELD
|
|
342
265
|
end
|
|
343
266
|
end
|
|
344
267
|
end
|
|
@@ -211,7 +211,7 @@ module Aspera
|
|
|
211
211
|
end
|
|
212
212
|
# add special key
|
|
213
213
|
package['items'] = package['link'].is_a?(Array) ? package['link'].length : 0
|
|
214
|
-
package['metadata'] = package['metadata']['field'].
|
|
214
|
+
package['metadata'] = package['metadata']['field'].to_h{ |i| [i['name'], i['content']]}
|
|
215
215
|
# if we look for a specific package
|
|
216
216
|
stop_condition = true if !stop_at_id.nil? && stop_at_id.eql?(package[PACKAGE_MATCH_FIELD])
|
|
217
217
|
# keep only those for the specified recipient
|
|
@@ -108,16 +108,17 @@ module Aspera
|
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
# if recipient is just an email, then convert to expected API hash : name and type
|
|
111
|
-
def normalize_recipients(parameters)
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
def normalize_recipients(parameters, type)
|
|
112
|
+
type = type.to_s
|
|
113
|
+
return unless parameters.key?(type)
|
|
114
|
+
Aspera.assert_type(parameters[type], Array){type}
|
|
114
115
|
recipient_types = Api::Faspex::RECIPIENT_TYPES
|
|
115
116
|
if parameters.key?('recipient_types')
|
|
116
117
|
recipient_types = parameters['recipient_types']
|
|
117
118
|
parameters.delete('recipient_types')
|
|
118
119
|
recipient_types = [recipient_types] unless recipient_types.is_a?(Array)
|
|
119
120
|
end
|
|
120
|
-
parameters[
|
|
121
|
+
parameters[type].map! do |recipient_data|
|
|
121
122
|
# If just a string, make a general lookup and build expected name/type hash
|
|
122
123
|
if recipient_data.is_a?(String)
|
|
123
124
|
matched = @api_v5.lookup_by_name('contacts', recipient_data, query: Rest.php_style({context: 'packages', type: recipient_types}))
|
|
@@ -157,7 +158,7 @@ module Aspera
|
|
|
157
158
|
end
|
|
158
159
|
end
|
|
159
160
|
|
|
160
|
-
# @param [
|
|
161
|
+
# @param [String] job identifier
|
|
161
162
|
# @return [Hash] result of API call for job status
|
|
162
163
|
def wait_for_job(job_id)
|
|
163
164
|
result = nil
|
|
@@ -182,13 +183,9 @@ module Aspera
|
|
|
182
183
|
when *Api::Faspex::API_LIST_MAILBOX_TYPES then "#{box}/packages"
|
|
183
184
|
else
|
|
184
185
|
group_type = options.get_option(:group_type)
|
|
185
|
-
"#{group_type}/#{lookup_entity_by_field(
|
|
186
|
+
"#{group_type}/#{@api_v5.lookup_entity_by_field(entity: group_type, value: box)['id']}/packages"
|
|
186
187
|
end
|
|
187
|
-
list, total = list_entities_limit_offset_total_count(
|
|
188
|
-
api: @api_v5,
|
|
189
|
-
entity: entity,
|
|
190
|
-
query: query_read_delete(default: query)
|
|
191
|
-
)
|
|
188
|
+
list, total = @api_v5.list_entities_limit_offset_total_count(entity: entity, query: query_read_delete(default: query))
|
|
192
189
|
return list.select(&filter), total
|
|
193
190
|
end
|
|
194
191
|
|
|
@@ -251,7 +248,7 @@ module Aspera
|
|
|
251
248
|
type: Api::Faspex.box_type(box),
|
|
252
249
|
transfer_type: Api::Faspex::TRANSFER_CONNECT
|
|
253
250
|
}
|
|
254
|
-
# download_params[:recipient_workgroup_id] = lookup_entity_by_field(
|
|
251
|
+
# download_params[:recipient_workgroup_id] = @api_v5.lookup_entity_by_field(entity: options.get_option(:group_type), value: box)['id'] if !Api::Faspex::API_LIST_MAILBOX_TYPES.include?(box) && box != SpecialValues::ALL
|
|
255
252
|
packages.each do |package|
|
|
256
253
|
pkg_id = package['id']
|
|
257
254
|
formatter.display_status("Receiving package #{pkg_id}")
|
|
@@ -286,7 +283,7 @@ module Aspera
|
|
|
286
283
|
recipient_type: @api_v5.pub_link_context['recipient_type']
|
|
287
284
|
}]
|
|
288
285
|
end
|
|
289
|
-
normalize_recipients(parameters)
|
|
286
|
+
PACKAGE_RECIPIENT_TYPES.each{ |type| normalize_recipients(parameters, type)}
|
|
290
287
|
# User specified content prot in tspec, but faspex requires in package creation
|
|
291
288
|
# `transfer_spec/upload` will set `content_protection`
|
|
292
289
|
if transfer.user_transfer_spec['content_protection'] && !parameters.key?('ear_enabled')
|
|
@@ -308,8 +305,7 @@ module Aspera
|
|
|
308
305
|
else
|
|
309
306
|
# send from remote shared folder
|
|
310
307
|
if (m = Base.percent_selector(shared_folder))
|
|
311
|
-
shared_folder = lookup_entity_by_field(
|
|
312
|
-
api: @api_v5,
|
|
308
|
+
shared_folder = @api_v5.lookup_entity_by_field(
|
|
313
309
|
entity: 'shared_folders',
|
|
314
310
|
field: m[:field],
|
|
315
311
|
value: m[:value]
|
|
@@ -464,12 +460,12 @@ module Aspera
|
|
|
464
460
|
case res_command
|
|
465
461
|
when *ALL_OPS
|
|
466
462
|
return entity_execute(command: res_command, **exec_args) do |field, value|
|
|
467
|
-
lookup_entity_by_field(
|
|
463
|
+
@api_v5.lookup_entity_by_field(entity: exec_args[:entity], value: value, field: field, items_key: exec_args[:items_key], query: res_id_query)['id']
|
|
468
464
|
end
|
|
469
465
|
when :shared_folders
|
|
470
466
|
# nodes
|
|
471
467
|
node_id = instance_identifier do |field, value|
|
|
472
|
-
lookup_entity_by_field(
|
|
468
|
+
@api_v5.lookup_entity_by_field(entity: 'nodes', field: field, value: value)['id']
|
|
473
469
|
end
|
|
474
470
|
shfld_entity = "nodes/#{node_id}/shared_folders"
|
|
475
471
|
sh_command = options.get_next_command(ALL_OPS + [:user])
|
|
@@ -480,33 +476,32 @@ module Aspera
|
|
|
480
476
|
entity: shfld_entity,
|
|
481
477
|
command: sh_command
|
|
482
478
|
) do |field, value|
|
|
483
|
-
lookup_entity_by_field(
|
|
479
|
+
@api_v5.lookup_entity_by_field(entity: shfld_entity, field: field, value: value)['id']
|
|
484
480
|
end
|
|
485
481
|
when :user
|
|
486
482
|
sh_id = instance_identifier do |field, value|
|
|
487
|
-
lookup_entity_by_field(
|
|
483
|
+
@api_v5.lookup_entity_by_field(entity: shfld_entity, field: field, value: value)['id']
|
|
488
484
|
end
|
|
489
485
|
user_path = "#{shfld_entity}/#{sh_id}/custom_access_users"
|
|
490
486
|
return entity_execute(api: @api_v5, entity: user_path, items_key: 'users') do |field, value|
|
|
491
|
-
lookup_entity_by_field(
|
|
487
|
+
@api_v5.lookup_entity_by_field(entity: user_path, items_key: 'users', field: field, value: value)['id']
|
|
492
488
|
end
|
|
493
489
|
|
|
494
490
|
end
|
|
495
491
|
when :browse
|
|
496
492
|
# nodes
|
|
497
493
|
node_id = instance_identifier do |field, value|
|
|
498
|
-
lookup_entity_by_field(
|
|
494
|
+
@api_v5.lookup_entity_by_field(entity: 'nodes', value: value, field: field)['id']
|
|
499
495
|
end
|
|
500
496
|
return browse_folder("nodes/#{node_id}/browse")
|
|
501
497
|
when :invite_external_collaborator
|
|
502
498
|
# :shared_inboxes, :workgroups
|
|
503
|
-
shared_inbox_id = instance_identifier{ |field, value| lookup_entity_by_field(
|
|
499
|
+
shared_inbox_id = instance_identifier{ |field, value| @api_v5.lookup_entity_by_field(entity: res_sym.to_s, field: field, value: value, query: res_id_query)['id']}
|
|
504
500
|
creation_payload = value_create_modify(command: res_command, type: [Hash, String])
|
|
505
501
|
creation_payload = {'email_address' => creation_payload} if creation_payload.is_a?(String)
|
|
506
502
|
result = @api_v5.create("#{res_sym}/#{shared_inbox_id}/external_collaborator", creation_payload)
|
|
507
503
|
formatter.display_status(result['message'])
|
|
508
|
-
result = lookup_entity_by_field(
|
|
509
|
-
api: @api_v5,
|
|
504
|
+
result = @api_v5.lookup_entity_by_field(
|
|
510
505
|
entity: "#{res_sym}/#{shared_inbox_id}/members",
|
|
511
506
|
items_key: 'members',
|
|
512
507
|
value: creation_payload['email_address'],
|
|
@@ -515,7 +510,7 @@ module Aspera
|
|
|
515
510
|
return Main.result_single_object(result)
|
|
516
511
|
when :members, :saml_groups
|
|
517
512
|
# res_command := :shared_inboxes, :workgroups
|
|
518
|
-
res_id = instance_identifier{ |field, value| lookup_entity_by_field(
|
|
513
|
+
res_id = instance_identifier{ |field, value| @api_v5.lookup_entity_by_field(entity: res_sym.to_s, field: field, value: value, query: res_id_query)['id']}
|
|
519
514
|
res_path = "#{res_sym}/#{res_id}/#{res_command}"
|
|
520
515
|
list_key = res_command.to_s
|
|
521
516
|
list_key = 'groups' if res_command.eql?(:saml_groups)
|
|
@@ -526,8 +521,7 @@ module Aspera
|
|
|
526
521
|
users = [users] unless users.is_a?(Array)
|
|
527
522
|
users = users.map do |user|
|
|
528
523
|
if (m = Base.percent_selector(user))
|
|
529
|
-
lookup_entity_by_field(
|
|
530
|
-
api: @api_v5,
|
|
524
|
+
@api_v5.lookup_entity_by_field(
|
|
531
525
|
entity: 'accounts',
|
|
532
526
|
field: m[:field],
|
|
533
527
|
value: m[:value],
|
|
@@ -548,8 +542,7 @@ module Aspera
|
|
|
548
542
|
command: sub_command,
|
|
549
543
|
items_key: list_key
|
|
550
544
|
) do |field, value|
|
|
551
|
-
lookup_entity_by_field(
|
|
552
|
-
api: @api_v5,
|
|
545
|
+
@api_v5.lookup_entity_by_field(
|
|
553
546
|
entity: res_path,
|
|
554
547
|
field: field,
|
|
555
548
|
value: value,
|
|
@@ -558,7 +551,7 @@ module Aspera
|
|
|
558
551
|
end
|
|
559
552
|
when :reset_password
|
|
560
553
|
# :accounts
|
|
561
|
-
contact_id = instance_identifier{ |field, value| lookup_entity_by_field(
|
|
554
|
+
contact_id = instance_identifier{ |field, value| @api_v5.lookup_entity_by_field(entity: 'accounts', field: field, value: value, query: res_id_query)['id']}
|
|
562
555
|
@api_v5.create("accounts/#{contact_id}/reset_password", {})
|
|
563
556
|
return Main.result_status('password reset, user shall check email')
|
|
564
557
|
end
|
|
@@ -579,16 +572,10 @@ module Aspera
|
|
|
579
572
|
event_type = options.get_next_command(%i[application webhook])
|
|
580
573
|
case event_type
|
|
581
574
|
when :application
|
|
582
|
-
list, total = list_entities_limit_offset_total_count(
|
|
583
|
-
api: @api_v5,
|
|
584
|
-
entity: 'application_events',
|
|
585
|
-
query: query_read_delete
|
|
586
|
-
)
|
|
587
|
-
|
|
575
|
+
list, total = @api_v5.list_entities_limit_offset_total_count(entity: 'application_events', query: query_read_delete)
|
|
588
576
|
return Main.result_object_list(list, total: total, fields: %w[event_type created_at application user.name])
|
|
589
577
|
when :webhook
|
|
590
|
-
list, total = list_entities_limit_offset_total_count(
|
|
591
|
-
api: @api_v5,
|
|
578
|
+
list, total = @api_v5.list_entities_limit_offset_total_count(
|
|
592
579
|
entity: 'all_webhooks_events',
|
|
593
580
|
query: query_read_delete,
|
|
594
581
|
items_key: 'events'
|
|
@@ -705,7 +692,7 @@ module Aspera
|
|
|
705
692
|
items_key: invitation_endpoint,
|
|
706
693
|
display_fields: %w[id public recipient_type recipient_name email_address]
|
|
707
694
|
) do |field, value|
|
|
708
|
-
lookup_entity_by_field(
|
|
695
|
+
@api_v5.lookup_entity_by_field(entity: invitation_endpoint, field: field, value: value, query: {})['id']
|
|
709
696
|
end
|
|
710
697
|
end
|
|
711
698
|
when :gateway
|
|
@@ -732,7 +719,8 @@ module Aspera
|
|
|
732
719
|
ACCOUNT_TYPES = %w{local_user saml_user self_registered_user external_user}.freeze
|
|
733
720
|
WORKGROUP_TYPES = %w{workgroup shared_inbox}.freeze
|
|
734
721
|
CONTACT_TYPES = (WORKGROUP_TYPES + %w{distribution_list user external_user}).freeze
|
|
735
|
-
|
|
722
|
+
PACKAGE_RECIPIENT_TYPES = %i{recipients private_recipients notified_on_upload notified_on_download notified_on_receipt}
|
|
723
|
+
private_constant :SHARED_INBOX_MEMBER_LEVELS, :ACCOUNT_TYPES, :CONTACT_TYPES, :PACKAGE_RECIPIENT_TYPES
|
|
736
724
|
end
|
|
737
725
|
end
|
|
738
726
|
end
|
|
@@ -928,10 +928,8 @@ module Aspera
|
|
|
928
928
|
# do not process last one
|
|
929
929
|
break if end_date.nil?
|
|
930
930
|
# init data for this period
|
|
931
|
-
period_bandwidth = Transfer::Spec::DIRECTION_ENUM_VALUES.map(&:to_sym).
|
|
932
|
-
|
|
933
|
-
h2[k2] = 0
|
|
934
|
-
end
|
|
931
|
+
period_bandwidth = Transfer::Spec::DIRECTION_ENUM_VALUES.map(&:to_sym).to_h do |direction|
|
|
932
|
+
[direction, dir_info.to_h{ |k2| [k2, 0]}]
|
|
935
933
|
end
|
|
936
934
|
# find all transfers that were active at this time
|
|
937
935
|
transfers_data.each do |transfer|
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
require 'aspera/cli/plugins/basic_auth'
|
|
4
4
|
require 'aspera/cli/plugins/node'
|
|
5
5
|
require 'aspera/assert'
|
|
6
|
+
require 'aspera/rest_list'
|
|
7
|
+
|
|
6
8
|
module Aspera
|
|
7
9
|
module Cli
|
|
8
10
|
module Plugins
|
|
@@ -128,7 +130,7 @@ module Aspera
|
|
|
128
130
|
when :admin
|
|
129
131
|
api_shares_admin = basic_auth_api(ADMIN_API_PATH)
|
|
130
132
|
admin_command = options.get_next_command(%i[node share transfer_settings user group].freeze)
|
|
131
|
-
lookup_share = ->(field, value){lookup_entity_generic(entity: 'share', field: field, value: value){api_shares_admin.read('data/shares')}['id']}
|
|
133
|
+
lookup_share = ->(field, value){RestList.lookup_entity_generic(entity: 'share', field: field, value: value){api_shares_admin.read('data/shares')}['id']}
|
|
132
134
|
case admin_command
|
|
133
135
|
when :node
|
|
134
136
|
return entity_execute(api: api_shares_admin, entity: 'data/nodes')
|
|
@@ -177,7 +179,7 @@ module Aspera
|
|
|
177
179
|
entity_commands = %i[import].freeze
|
|
178
180
|
end
|
|
179
181
|
entity_verb = options.get_next_command(entity_commands)
|
|
180
|
-
lookup_block = ->(field, value){lookup_entity_generic(entity: entity_type, field: field, value: value){api_shares_admin.read(entities_path)}['id']}
|
|
182
|
+
lookup_block = ->(field, value){RestList.lookup_entity_generic(entity: entity_type, field: field, value: value){api_shares_admin.read(entities_path)}['id']}
|
|
181
183
|
case entity_verb
|
|
182
184
|
when *ALL_OPS # list, show, delete, create, modify
|
|
183
185
|
display_fields = entity_type.eql?(:user) ? %w[id user_id username first_name last_name email] : nil
|
|
@@ -33,6 +33,9 @@ module Aspera
|
|
|
33
33
|
:DEFAULT_TRANSFER_NOTIFY_TEMPLATE
|
|
34
34
|
|
|
35
35
|
class << self
|
|
36
|
+
# Analyze transfer session statuses and return a global status
|
|
37
|
+
#
|
|
38
|
+
# @param statuses [Array] list of session status, each status is :success or an error message string
|
|
36
39
|
# @return [:success] if all sessions statuses returned by "start" are success
|
|
37
40
|
# @return [Exception] if one sessions statuses returned by "start" is failed
|
|
38
41
|
def session_status(statuses)
|