aspera-cli 4.24.2 → 4.25.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 +1064 -758
- data/CONTRIBUTING.md +43 -100
- data/README.md +671 -419
- data/lib/aspera/api/aoc.rb +71 -43
- data/lib/aspera/api/cos_node.rb +3 -2
- data/lib/aspera/api/faspex.rb +6 -5
- data/lib/aspera/api/node.rb +10 -12
- data/lib/aspera/ascmd.rb +1 -2
- data/lib/aspera/ascp/installation.rb +53 -39
- data/lib/aspera/assert.rb +25 -3
- data/lib/aspera/cli/error.rb +4 -2
- data/lib/aspera/cli/extended_value.rb +84 -60
- data/lib/aspera/cli/formatter.rb +55 -22
- data/lib/aspera/cli/main.rb +21 -14
- data/lib/aspera/cli/manager.rb +348 -247
- data/lib/aspera/cli/plugins/alee.rb +3 -3
- data/lib/aspera/cli/plugins/aoc.rb +70 -14
- data/lib/aspera/cli/plugins/base.rb +57 -49
- data/lib/aspera/cli/plugins/config.rb +69 -84
- data/lib/aspera/cli/plugins/console.rb +13 -8
- data/lib/aspera/cli/plugins/cos.rb +1 -1
- data/lib/aspera/cli/plugins/faspex.rb +32 -26
- data/lib/aspera/cli/plugins/faspex5.rb +45 -43
- data/lib/aspera/cli/plugins/faspio.rb +5 -5
- data/lib/aspera/cli/plugins/httpgw.rb +1 -1
- data/lib/aspera/cli/plugins/node.rb +131 -120
- data/lib/aspera/cli/plugins/oauth.rb +1 -1
- data/lib/aspera/cli/plugins/orchestrator.rb +114 -32
- data/lib/aspera/cli/plugins/preview.rb +26 -46
- data/lib/aspera/cli/plugins/server.rb +6 -8
- data/lib/aspera/cli/plugins/shares.rb +27 -32
- data/lib/aspera/cli/sync_actions.rb +49 -38
- data/lib/aspera/cli/transfer_agent.rb +16 -34
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +8 -5
- data/lib/aspera/command_line_builder.rb +20 -17
- data/lib/aspera/coverage.rb +1 -1
- data/lib/aspera/environment.rb +41 -34
- data/lib/aspera/faspex_gw.rb +1 -1
- data/lib/aspera/keychain/factory.rb +1 -2
- data/lib/aspera/markdown.rb +31 -0
- data/lib/aspera/nagios.rb +6 -5
- data/lib/aspera/oauth/base.rb +17 -27
- data/lib/aspera/oauth/factory.rb +1 -1
- data/lib/aspera/oauth/url_json.rb +2 -1
- data/lib/aspera/preview/file_types.rb +23 -37
- data/lib/aspera/products/connect.rb +3 -3
- data/lib/aspera/rest.rb +51 -39
- data/lib/aspera/rest_error_analyzer.rb +4 -4
- data/lib/aspera/ssh.rb +5 -2
- data/lib/aspera/ssl.rb +41 -0
- data/lib/aspera/sync/conf.schema.yaml +182 -34
- data/lib/aspera/sync/database.rb +2 -1
- data/lib/aspera/sync/operations.rb +125 -69
- data/lib/aspera/transfer/parameters.rb +3 -4
- data/lib/aspera/transfer/spec.rb +2 -3
- data/lib/aspera/transfer/spec.schema.yaml +48 -18
- data/lib/aspera/transfer/spec_doc.rb +14 -14
- data/lib/aspera/uri_reader.rb +1 -1
- data/lib/transferd_pb.rb +2 -2
- data.tar.gz.sig +0 -0
- metadata +19 -6
- metadata.gz.sig +3 -2
|
@@ -17,13 +17,13 @@ module Aspera
|
|
|
17
17
|
nagios = Nagios.new
|
|
18
18
|
begin
|
|
19
19
|
api = Api::Alee.new(nil, nil, version: 'ping')
|
|
20
|
-
|
|
21
|
-
raise "unexpected response: #{
|
|
20
|
+
http = api.read(nil, ret: :resp)
|
|
21
|
+
raise "unexpected response: #{http.body}" unless http.body.eql?('pong')
|
|
22
22
|
nagios.add_ok('api', 'answered ok')
|
|
23
23
|
rescue StandardError => e
|
|
24
24
|
nagios.add_critical('api', e.to_s)
|
|
25
25
|
end
|
|
26
|
-
|
|
26
|
+
Main.result_object_list(nagios.status_list)
|
|
27
27
|
when :entitlement
|
|
28
28
|
entitlement_id = options.get_option(:username, mandatory: true)
|
|
29
29
|
customer_id = options.get_option(:password, mandatory: true)
|
|
@@ -69,9 +69,9 @@ module Aspera
|
|
|
69
69
|
base_url = "#{base_url}.#{Api::AoC::SAAS_DOMAIN_PROD}" unless base_url.include?('.')
|
|
70
70
|
# AoC is only https
|
|
71
71
|
return unless base_url.start_with?('https://')
|
|
72
|
-
|
|
73
|
-
return if
|
|
74
|
-
redirect_uri = URI.parse(
|
|
72
|
+
location = Rest.new(base_url: base_url, redirect_max: 0).call(operation: 'GET', subpath: 'auth/ping', exception: false, ret: :resp)['Location']
|
|
73
|
+
return if location.nil?
|
|
74
|
+
redirect_uri = URI.parse(location)
|
|
75
75
|
od = Api::AoC.split_org_domain(URI.parse(base_url))
|
|
76
76
|
return unless redirect_uri.path.end_with?("oauth2/#{od[:organization]}/login")
|
|
77
77
|
# either in standard domain, or product name in page
|
|
@@ -132,7 +132,7 @@ module Aspera
|
|
|
132
132
|
test_args: 'organization'
|
|
133
133
|
}
|
|
134
134
|
end
|
|
135
|
-
options.declare(:use_generic_client, 'Wizard: AoC: use global or org specific jwt client id',
|
|
135
|
+
options.declare(:use_generic_client, 'Wizard: AoC: use global or org specific jwt client id', allowed: Allowed::TYPES_BOOLEAN, default: Api::AoC.saas_url?(app_url))
|
|
136
136
|
options.parse_options!
|
|
137
137
|
# make username mandatory for jwt, this triggers interactive input
|
|
138
138
|
wiz_username = options.get_option(:username, mandatory: true)
|
|
@@ -205,10 +205,10 @@ module Aspera
|
|
|
205
205
|
@cache_workspace_info = nil
|
|
206
206
|
@cache_home_node_file = nil
|
|
207
207
|
@cache_api_aoc = nil
|
|
208
|
-
options.declare(:workspace, 'Name of workspace',
|
|
209
|
-
options.declare(:new_user_option, 'New user creation option for unknown package recipients',
|
|
210
|
-
options.declare(:validate_metadata, 'Validate shared inbox metadata',
|
|
211
|
-
options.declare(:package_folder, 'Field of package to use as folder name, or @none:',
|
|
208
|
+
options.declare(:workspace, 'Name of workspace', allowed: [String, NilClass], default: Api::AoC::DEFAULT_WORKSPACE)
|
|
209
|
+
options.declare(:new_user_option, 'New user creation option for unknown package recipients', allowed: Hash)
|
|
210
|
+
options.declare(:validate_metadata, 'Validate shared inbox metadata', allowed: Allowed::TYPES_BOOLEAN, default: true)
|
|
211
|
+
options.declare(:package_folder, 'Field of package to use as folder name, or @none:', allowed: [String, NilClass])
|
|
212
212
|
options.parse_options!
|
|
213
213
|
# add node plugin options (for manual)
|
|
214
214
|
Node.declare_options(options)
|
|
@@ -288,7 +288,7 @@ module Aspera
|
|
|
288
288
|
query = query_read_delete(default: default_query)
|
|
289
289
|
# caller may add specific modifications or checks to query
|
|
290
290
|
yield(query) if block_given?
|
|
291
|
-
result = aoc_api.read_with_paging(resource_class_path,
|
|
291
|
+
result = aoc_api.read_with_paging(resource_class_path, base_query.merge(query).compact, formatter: formatter)
|
|
292
292
|
return Main.result_object_list(result[:items], fields: fields, total: result[:total])
|
|
293
293
|
end
|
|
294
294
|
|
|
@@ -313,7 +313,7 @@ module Aspera
|
|
|
313
313
|
Aspera.assert_type(query, Hash){'query'}
|
|
314
314
|
PACKAGE_RECEIVED_BASE_QUERY.each{ |k, v| query[k] = v unless query.key?(k)}
|
|
315
315
|
resolve_dropbox_name_default_ws_id(query)
|
|
316
|
-
return aoc_api.read_with_paging('packages', query
|
|
316
|
+
return aoc_api.read_with_paging('packages', query.compact, formatter: formatter)
|
|
317
317
|
end
|
|
318
318
|
|
|
319
319
|
NODE4_EXT_COMMANDS = %i[transfer].concat(Node::COMMANDS_GEN4).freeze
|
|
@@ -374,6 +374,7 @@ module Aspera
|
|
|
374
374
|
Aspera.error_unreachable_line
|
|
375
375
|
end
|
|
376
376
|
|
|
377
|
+
# @param resource_type [Symbol] One of ADMIN_OBJECTS
|
|
377
378
|
def execute_resource_action(resource_type)
|
|
378
379
|
# get path on API, resource type is singular, but api is plural
|
|
379
380
|
resource_class_path =
|
|
@@ -391,8 +392,9 @@ module Aspera
|
|
|
391
392
|
global_operations = %i[create list]
|
|
392
393
|
supported_operations = %i[show modify]
|
|
393
394
|
supported_operations.push(:delete, *global_operations) unless singleton_object
|
|
394
|
-
supported_operations.push(:do) if resource_type.eql?(:node)
|
|
395
|
+
supported_operations.push(:do, :bearer_token) if resource_type.eql?(:node)
|
|
395
396
|
supported_operations.push(:set_pub_key) if resource_type.eql?(:client)
|
|
397
|
+
supported_operations.push(:shared_folder, :dropbox) if resource_type.eql?(:workspace)
|
|
396
398
|
command = options.get_next_command(supported_operations)
|
|
397
399
|
# require identifier for non global commands
|
|
398
400
|
if !singleton_object && !global_operations.include?(command)
|
|
@@ -454,6 +456,60 @@ module Aspera
|
|
|
454
456
|
when :do
|
|
455
457
|
command_repo = options.get_next_command(NODE4_EXT_COMMANDS)
|
|
456
458
|
return execute_nodegen4_command(command_repo, res_id)
|
|
459
|
+
when :bearer_token
|
|
460
|
+
node_api = aoc_api.node_api_from(
|
|
461
|
+
node_id: res_id,
|
|
462
|
+
scope: options.get_next_argument('scope')
|
|
463
|
+
)
|
|
464
|
+
return Main.result_text(node_api.oauth.authorization)
|
|
465
|
+
when :dropbox
|
|
466
|
+
command_shared = options.get_next_command(%i[list])
|
|
467
|
+
case command_shared
|
|
468
|
+
when :list
|
|
469
|
+
query = options.get_option(:query) || {}
|
|
470
|
+
res_data = aoc_api.read('dropboxes', query.merge({'workspace_id'=>res_id}))
|
|
471
|
+
return Main.result_object_list(res_data, fields: %w[id name description])
|
|
472
|
+
end
|
|
473
|
+
when :shared_folder
|
|
474
|
+
query = options.get_option(:query) || Api::AoC.workspace_access(res_id).merge({'admin' => true})
|
|
475
|
+
shared_folders = aoc_api.read_with_paging("#{resource_instance_path}/permissions", query)[:items]
|
|
476
|
+
# inside a workspace
|
|
477
|
+
command_shared = options.get_next_command(%i[list member])
|
|
478
|
+
case command_shared
|
|
479
|
+
when :list
|
|
480
|
+
return Main.result_object_list(shared_folders, fields: %w[id node_name node_id file_id file.path tags.aspera.files.workspace.share_as])
|
|
481
|
+
when :member
|
|
482
|
+
shared_folder_id = instance_identifier
|
|
483
|
+
shared_folder = shared_folders.find{ |i| i['id'].eql?(shared_folder_id)}
|
|
484
|
+
Aspera.assert(shared_folder)
|
|
485
|
+
command_shared_member = options.get_next_command(%i[list])
|
|
486
|
+
case command_shared_member
|
|
487
|
+
when :list
|
|
488
|
+
node_api = aoc_api.node_api_from(
|
|
489
|
+
node_id: shared_folder['node_id'],
|
|
490
|
+
workspace_id: res_id,
|
|
491
|
+
workspace_name: nil,
|
|
492
|
+
scope: Api::Node::SCOPE_USER
|
|
493
|
+
)
|
|
494
|
+
result = node_api.read(
|
|
495
|
+
'permissions',
|
|
496
|
+
{'file_id' => shared_folder['file_id'], 'tag' => "aspera.files.workspace.id=#{res_id}"}
|
|
497
|
+
)
|
|
498
|
+
result.each do |item|
|
|
499
|
+
item['member'] = begin
|
|
500
|
+
if Api::AoC.workspace_access?(item)
|
|
501
|
+
{'name'=>'[Internal permission]'}
|
|
502
|
+
else
|
|
503
|
+
aoc_api.read("admin/#{item['access_type']}s/#{item['access_id']}") rescue {'name': 'not found'}
|
|
504
|
+
end
|
|
505
|
+
rescue => e
|
|
506
|
+
{'name'=>e.to_s}
|
|
507
|
+
end
|
|
508
|
+
end
|
|
509
|
+
# TODO : read users and group name and add, if query "include_members"
|
|
510
|
+
return Main.result_object_list(result, fields: %w[access_type access_id access_level last_updated_at member.name member.email member.system_group_type member.system_group])
|
|
511
|
+
end
|
|
512
|
+
end
|
|
457
513
|
else Aspera.error_unexpected_value(command)
|
|
458
514
|
end
|
|
459
515
|
end
|
|
@@ -736,7 +792,7 @@ module Aspera
|
|
|
736
792
|
}
|
|
737
793
|
return result_list('short_links', fields: Formatter.all_but('data'), base_query: list_params) if command.eql?(:list)
|
|
738
794
|
one_id = instance_identifier
|
|
739
|
-
found = aoc_api.read_with_paging('short_links',
|
|
795
|
+
found = aoc_api.read_with_paging('short_links', list_params, formatter: formatter)[:items].find{ |item| item['id'].eql?(one_id)}
|
|
740
796
|
raise Cli::BadIdentifier.new('Short link', one_id) if found.nil?
|
|
741
797
|
return Main.result_single_object(found, fields: Formatter.all_but('data'))
|
|
742
798
|
when :modify
|
|
@@ -886,7 +942,7 @@ module Aspera
|
|
|
886
942
|
# enforce workspace id from link (should be already ok, but in case user wanted to override)
|
|
887
943
|
package_data['workspace_id'] = aoc_api.public_link['data']['workspace_id']
|
|
888
944
|
end
|
|
889
|
-
package_data['encryption_at_rest'] = true if transfer.
|
|
945
|
+
package_data['encryption_at_rest'] = true if transfer.user_transfer_spec['content_protection'].eql?('encrypt')
|
|
890
946
|
# transfer may raise an error
|
|
891
947
|
created_package = aoc_api.create_package_simple(package_data, option_validate, new_user_option)
|
|
892
948
|
Main.result_transfer(transfer.start(created_package[:spec], rest_token: created_package[:node]))
|
|
@@ -949,7 +1005,7 @@ module Aspera
|
|
|
949
1005
|
destination_folder,
|
|
950
1006
|
Environment.instance.sanitized_filename(package_info[per_package_field1])
|
|
951
1007
|
)
|
|
952
|
-
transfer.
|
|
1008
|
+
transfer.user_transfer_spec['destination_root'] = self.class.unique_folder(
|
|
953
1009
|
folder,
|
|
954
1010
|
extension: per_package_field2.eql?('seq') ? :seq : package_info[per_package_field2],
|
|
955
1011
|
always: per_package_sub_always
|
|
@@ -18,15 +18,22 @@ module Aspera
|
|
|
18
18
|
MAX_ITEMS = 'max'
|
|
19
19
|
# Special query parameter: `pmax`: max number of pages for list command
|
|
20
20
|
MAX_PAGES = 'pmax'
|
|
21
|
-
# Special identifier format: look for this name to find where supported
|
|
22
|
-
REGEX_LOOKUP_ID_BY_FIELD = /^%([^:]+):(.*)$/
|
|
23
21
|
|
|
24
22
|
class << self
|
|
25
23
|
def declare_options(options)
|
|
26
|
-
options.declare(:query, 'Additional filter for for some commands (list/delete)',
|
|
24
|
+
options.declare(:query, 'Additional filter for for some commands (list/delete)', allowed: [Hash, Array, NilClass])
|
|
27
25
|
options.declare(:property, 'Name of property to set (modify operation)')
|
|
28
|
-
options.declare(:bulk, 'Bulk operation (only some)',
|
|
29
|
-
options.declare(:bfail, 'Bulk operation error handling',
|
|
26
|
+
options.declare(:bulk, 'Bulk operation (only some)', allowed: Allowed::TYPES_BOOLEAN, default: false)
|
|
27
|
+
options.declare(:bfail, 'Bulk operation error handling', allowed: Allowed::TYPES_BOOLEAN, default: true)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @return [Hash,NilClass] `{field:,value:}` if identifier is a percent selector, else `nil`
|
|
31
|
+
def percent_selector(identifier)
|
|
32
|
+
Aspera.assert_type(identifier, String)
|
|
33
|
+
if (m = identifier.match(REGEX_LOOKUP_ID_BY_FIELD))
|
|
34
|
+
return {field: m[1], value: ExtendedValue.instance.evaluate(m[2], context: "percent selector: #{m[1]}")}
|
|
35
|
+
end
|
|
36
|
+
return
|
|
30
37
|
end
|
|
31
38
|
end
|
|
32
39
|
|
|
@@ -55,26 +62,17 @@ module Aspera
|
|
|
55
62
|
options.parser.separator('OPTIONS:') if has_options
|
|
56
63
|
end
|
|
57
64
|
|
|
58
|
-
#
|
|
59
|
-
# ... folder browse _call_instance_identifier
|
|
65
|
+
# Resource identifier as positional parameter
|
|
60
66
|
#
|
|
61
67
|
# @param description [String] description of the identifier
|
|
62
|
-
# @param as_option [Symbol] option name to use if identifier is an option
|
|
63
68
|
# @param block [Proc] block to search for identifier based on attribute value
|
|
64
69
|
# @return [String, Array] identifier or list of ids
|
|
65
|
-
def instance_identifier(description: 'identifier',
|
|
66
|
-
if
|
|
67
|
-
res_id = options.get_next_argument(description, multiple: options.get_option(:bulk)) if res_id.nil?
|
|
68
|
-
else
|
|
69
|
-
res_id = options.get_option(as_option)
|
|
70
|
-
end
|
|
70
|
+
def instance_identifier(description: 'identifier', &block)
|
|
71
|
+
res_id = options.get_next_argument(description, multiple: options.get_option(:bulk)) if res_id.nil?
|
|
71
72
|
# Can be an Array
|
|
72
|
-
if res_id.is_a?(String) && (m =
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
else
|
|
76
|
-
raise Cli::BadArgument, "Percent syntax for #{description} not supported in this context"
|
|
77
|
-
end
|
|
73
|
+
if res_id.is_a?(String) && (m = Base.percent_selector(res_id))
|
|
74
|
+
Aspera.assert(block, type: Cli::BadArgument){"Percent syntax for #{description} not supported in this context"}
|
|
75
|
+
res_id = yield(m[:field], m[:value])
|
|
78
76
|
end
|
|
79
77
|
return res_id
|
|
80
78
|
end
|
|
@@ -172,12 +170,11 @@ module Aspera
|
|
|
172
170
|
if !delete_style.nil?
|
|
173
171
|
one_res_id = [one_res_id] unless one_res_id.is_a?(Array)
|
|
174
172
|
Aspera.assert_type(one_res_id, Array, type: Cli::BadArgument)
|
|
175
|
-
api.
|
|
176
|
-
|
|
177
|
-
|
|
173
|
+
api.delete(
|
|
174
|
+
entity,
|
|
175
|
+
nil,
|
|
178
176
|
content_type: Rest::MIME_JSON,
|
|
179
|
-
body: {delete_style => one_res_id}
|
|
180
|
-
headers: {'Accept' => Rest::MIME_JSON}
|
|
177
|
+
body: {delete_style => one_res_id}
|
|
181
178
|
)
|
|
182
179
|
return Main.result_status('deleted')
|
|
183
180
|
end
|
|
@@ -192,11 +189,10 @@ module Aspera
|
|
|
192
189
|
data, total = list_entities_limit_offset_total_count(api: api, entity:, items_key: items_key, query: query_read_delete(default: list_query))
|
|
193
190
|
return Main.result_object_list(data, total: total, fields: display_fields)
|
|
194
191
|
end
|
|
195
|
-
|
|
196
|
-
return Main.result_empty if
|
|
197
|
-
data = resp[:data]
|
|
192
|
+
data, http = api.read(entity, query_read_delete, ret: :both)
|
|
193
|
+
return Main.result_empty if http.code == '204'
|
|
198
194
|
# TODO: not generic : which application is this for ?
|
|
199
|
-
if
|
|
195
|
+
if http['Content-Type'].start_with?('application/vnd.api+json')
|
|
200
196
|
Log.log.debug('is vnd.api')
|
|
201
197
|
data = data[entity]
|
|
202
198
|
end
|
|
@@ -223,9 +219,8 @@ module Aspera
|
|
|
223
219
|
|
|
224
220
|
# Query parameters in URL suitable for REST: list/GET and delete/DELETE
|
|
225
221
|
def query_read_delete(default: nil)
|
|
226
|
-
query = options.get_option(:query)
|
|
227
222
|
# Dup default, as it could be frozen
|
|
228
|
-
query =
|
|
223
|
+
query = options.get_option(:query) || default.dup
|
|
229
224
|
Log.log.debug{"query_read_delete=#{query}".bg_red}
|
|
230
225
|
begin
|
|
231
226
|
# Check it is suitable
|
|
@@ -249,7 +244,7 @@ module Aspera
|
|
|
249
244
|
value = default if value.nil?
|
|
250
245
|
unless type.nil?
|
|
251
246
|
type = [type] unless type.is_a?(Array)
|
|
252
|
-
Aspera.
|
|
247
|
+
Aspera.assert_array_all(type, Class){'check types'}
|
|
253
248
|
if bulk
|
|
254
249
|
Aspera.assert_type(value, Array, type: Cli::BadArgument)
|
|
255
250
|
value.each do |v|
|
|
@@ -263,10 +258,10 @@ module Aspera
|
|
|
263
258
|
end
|
|
264
259
|
|
|
265
260
|
# Get a (full or partial) list of all entities of a given type with query: offset/limit
|
|
266
|
-
# @param
|
|
267
|
-
# @param
|
|
268
|
-
# @param
|
|
269
|
-
# @param
|
|
261
|
+
# @param api [Rest] API object
|
|
262
|
+
# @param entity [String,Symbol] API endpoint of entity to list
|
|
263
|
+
# @param items_key [String] Key in the result to get the list of items (Default: same as `entity`)
|
|
264
|
+
# @param query [Hash,nil] Additional query parameters
|
|
270
265
|
# @return [Array] items, total_count
|
|
271
266
|
def list_entities_limit_offset_total_count(
|
|
272
267
|
api:,
|
|
@@ -309,26 +304,39 @@ module Aspera
|
|
|
309
304
|
return result, total_count
|
|
310
305
|
end
|
|
311
306
|
|
|
312
|
-
# Lookup an entity id from its name
|
|
313
|
-
#
|
|
314
|
-
# @param
|
|
315
|
-
# @param
|
|
316
|
-
# @param
|
|
317
|
-
# @param
|
|
307
|
+
# Lookup an entity id from its name.
|
|
308
|
+
# Uses query `q` if `query` is `:default` and `field` is `name`.
|
|
309
|
+
# @param entity [String] Type of entity to lookup, by default it is the path, and it is also the field name in result
|
|
310
|
+
# @param value [String] Value to lookup
|
|
311
|
+
# @param field [String] Field to match, by default it is `'name'`
|
|
312
|
+
# @param items_key [String] Key in the result to get the list of items (override entity)
|
|
313
|
+
# @param query [Hash] Additional query parameters (Default: `:default`)
|
|
318
314
|
def lookup_entity_by_field(api:, entity:, value:, field: 'name', items_key: nil, query: :default)
|
|
319
315
|
if query.eql?(:default)
|
|
320
316
|
Aspera.assert(field.eql?('name')){'Default query is on name only'}
|
|
321
317
|
query = {'q'=> value}
|
|
322
318
|
end
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
319
|
+
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}
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
# Lookup entity by field and value. Extract single result from list of result returned by block.
|
|
323
|
+
# @param entity [String] Type of entity to lookup, by default it is the path, and it is also the field name in result
|
|
324
|
+
# @param value [String] Value to lookup
|
|
325
|
+
# @param field [String] Field to match, by default it is `'name'`
|
|
326
|
+
# @param block [Proc] Get list of entity matching query.
|
|
327
|
+
def lookup_entity_generic(entity:, value:, field: 'name', &block)
|
|
328
|
+
Aspera.assert(block_given?)
|
|
329
|
+
found = yield
|
|
330
|
+
Aspera.assert_array_all(found, Hash)
|
|
331
|
+
found = found.select{ |i| i[field].eql?(value)}
|
|
332
|
+
return found.first if found.length.eql?(1)
|
|
333
|
+
raise Cli::BadIdentifier.new(entity, value, field: field, count: found.length)
|
|
329
334
|
end
|
|
335
|
+
|
|
330
336
|
PER_PAGE_DEFAULT = 1000
|
|
331
|
-
|
|
337
|
+
# Percent selector: select by this field for this value
|
|
338
|
+
REGEX_LOOKUP_ID_BY_FIELD = /^%([^:]+):(.*)$/
|
|
339
|
+
private_constant :PER_PAGE_DEFAULT, :REGEX_LOOKUP_ID_BY_FIELD
|
|
332
340
|
end
|
|
333
341
|
end
|
|
334
342
|
end
|