aspera-cli 4.26.0 → 4.26.2

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.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +36 -4
  4. data/CONTRIBUTING.md +2 -5
  5. data/bin/ascli +2 -2
  6. data/lib/aspera/agent/direct.rb +1 -1
  7. data/lib/aspera/agent/factory.rb +4 -0
  8. data/lib/aspera/agent/httpgw.rb +1 -1
  9. data/lib/aspera/agent/node.rb +2 -2
  10. data/lib/aspera/api/aoc.rb +45 -37
  11. data/lib/aspera/api/cos_node.rb +1 -1
  12. data/lib/aspera/api/faspex.rb +7 -6
  13. data/lib/aspera/api/node.rb +9 -9
  14. data/lib/aspera/ascmd.rb +4 -4
  15. data/lib/aspera/ascp/installation.rb +13 -6
  16. data/lib/aspera/assert.rb +17 -13
  17. data/lib/aspera/cli/context.rb +58 -0
  18. data/lib/aspera/cli/extended_value.rb +9 -4
  19. data/lib/aspera/cli/formatter.rb +91 -187
  20. data/lib/aspera/cli/http.rb +167 -0
  21. data/lib/aspera/cli/manager.rb +132 -77
  22. data/lib/aspera/cli/options.schema.yaml +82 -0
  23. data/lib/aspera/cli/plugins/alee.rb +2 -2
  24. data/lib/aspera/cli/plugins/aoc.rb +113 -77
  25. data/lib/aspera/cli/plugins/ats.rb +16 -16
  26. data/lib/aspera/cli/plugins/base.rb +64 -49
  27. data/lib/aspera/cli/plugins/config.rb +172 -444
  28. data/lib/aspera/cli/plugins/console.rb +7 -7
  29. data/lib/aspera/cli/plugins/cos.rb +2 -2
  30. data/lib/aspera/cli/plugins/factory.rb +3 -0
  31. data/lib/aspera/cli/plugins/faspex.rb +22 -22
  32. data/lib/aspera/cli/plugins/faspex5.rb +68 -49
  33. data/lib/aspera/cli/plugins/faspio.rb +1 -1
  34. data/lib/aspera/cli/plugins/httpgw.rb +2 -2
  35. data/lib/aspera/cli/plugins/node.rb +80 -80
  36. data/lib/aspera/cli/plugins/orchestrator.rb +21 -26
  37. data/lib/aspera/cli/plugins/preview.rb +9 -9
  38. data/lib/aspera/cli/plugins/server.rb +7 -7
  39. data/lib/aspera/cli/plugins/shares.rb +2 -2
  40. data/lib/aspera/cli/preset_manager.rb +235 -0
  41. data/lib/aspera/cli/result.rb +310 -0
  42. data/lib/aspera/cli/{main.rb → runner.rb} +48 -130
  43. data/lib/aspera/cli/sync_actions.rb +15 -11
  44. data/lib/aspera/cli/terminal_formatter.rb +65 -0
  45. data/lib/aspera/cli/transfer_agent.rb +17 -15
  46. data/lib/aspera/cli/transfer_progress.rb +6 -6
  47. data/lib/aspera/cli/version.rb +1 -1
  48. data/lib/aspera/cli/wizard.rb +5 -6
  49. data/lib/aspera/command_line_builder.rb +22 -18
  50. data/lib/aspera/data_repository.rb +4 -0
  51. data/lib/aspera/dot_container.rb +1 -1
  52. data/lib/aspera/environment.rb +25 -6
  53. data/lib/aspera/faspex_gw.rb +1 -1
  54. data/lib/aspera/formatter_interface.rb +14 -0
  55. data/lib/aspera/hash_ext.rb +6 -0
  56. data/lib/aspera/json_rpc.rb +6 -5
  57. data/lib/aspera/keychain/base.rb +1 -1
  58. data/lib/aspera/keychain/encrypted_hash.rb +1 -1
  59. data/lib/aspera/keychain/factory.rb +1 -1
  60. data/lib/aspera/keychain/macos_security.rb +1 -1
  61. data/lib/aspera/log.rb +10 -5
  62. data/lib/aspera/markdown.rb +4 -1
  63. data/lib/aspera/nagios.rb +2 -2
  64. data/lib/aspera/oauth/base.rb +5 -5
  65. data/lib/aspera/oauth/boot.rb +43 -0
  66. data/lib/aspera/oauth/factory.rb +38 -14
  67. data/lib/aspera/oauth/web.rb +2 -2
  68. data/lib/aspera/oauth.rb +1 -0
  69. data/lib/aspera/persistency_action_once.rb +2 -2
  70. data/lib/aspera/preview/file_types.rb +4 -0
  71. data/lib/aspera/products/connect.rb +3 -0
  72. data/lib/aspera/products/transferd.rb +2 -2
  73. data/lib/aspera/proxy_auto_config.rb +6 -3
  74. data/lib/aspera/rest.rb +9 -5
  75. data/lib/aspera/rest_error_analyzer.rb +4 -0
  76. data/lib/aspera/rest_list.rb +10 -3
  77. data/lib/aspera/schema/IBM Aspera Faspex API-5.0-enhanced.yaml +62811 -0
  78. data/lib/aspera/schema/IBM Aspera on Cloud API-0.2.6-enhanced.yaml +9637 -0
  79. data/lib/aspera/schema/async_tables.yaml +361 -0
  80. data/lib/aspera/schema/documentation.rb +107 -0
  81. data/lib/aspera/schema/reader.rb +75 -0
  82. data/lib/aspera/schema/registry.rb +70 -0
  83. data/lib/aspera/secret_hider.rb +4 -0
  84. data/lib/aspera/sync/conf.schema.yaml +0 -26
  85. data/lib/aspera/sync/database.rb +14 -10
  86. data/lib/aspera/sync/operations.rb +14 -10
  87. data/lib/aspera/temp_file_manager.rb +4 -0
  88. data/lib/aspera/transfer/faux_file.rb +1 -1
  89. data/lib/aspera/transfer/parameters.rb +4 -4
  90. data/lib/aspera/transfer/resumer.rb +2 -2
  91. data/lib/aspera/transfer/spec.rb +3 -3
  92. data/lib/aspera/transfer/spec.schema.yaml +18 -9
  93. data/lib/aspera/transfer/uri.rb +1 -1
  94. data/lib/aspera/uri_reader.rb +1 -1
  95. data/lib/aspera/yaml.rb +4 -2
  96. data.tar.gz.sig +0 -0
  97. metadata +28 -15
  98. metadata.gz.sig +1 -1
  99. data/lib/aspera/transfer/spec_doc.rb +0 -76
@@ -97,7 +97,7 @@ module Aspera
97
97
  rescue StandardError => e
98
98
  nagios.add_critical('console api', e.to_s)
99
99
  end
100
- Main.result_object_list(nagios.status_list)
100
+ Result::ObjectList.new(nagios.status_list)
101
101
  when :transfer
102
102
  command = options.get_next_command(%i[current smart])
103
103
  case command
@@ -105,11 +105,11 @@ module Aspera
105
105
  command = options.get_next_command(%i[list submit])
106
106
  case command
107
107
  when :list
108
- return Main.result_object_list(api_console.read('smart_transfers'))
108
+ return Result::ObjectList.new(api_console.read('smart_transfers'))
109
109
  when :submit
110
110
  smart_id = options.get_next_argument('smart_id')
111
111
  params = options.get_next_argument('transfer parameters', validation: Hash)
112
- return Main.result_object_list(api_console.create("smart_transfers/#{smart_id}", params))
112
+ return Result::ObjectList.new(api_console.create("smart_transfers/#{smart_id}", params))
113
113
  end
114
114
  when :current
115
115
  command = options.get_next_command(%i[list show files start pause cancel resume rerun change_rate change_policy move_forwards move_back])
@@ -125,21 +125,21 @@ module Aspera
125
125
  if (filter = query.delete('filter'))
126
126
  parse_extended_filter(filter, query)
127
127
  end
128
- return Main.result_object_list(
128
+ return Result::ObjectList.new(
129
129
  api_console.read('transfers', query),
130
130
  fields: %w[id contact name status]
131
131
  )
132
132
  when :show
133
133
  transfer_id = options.instance_identifier(description: 'transfer ID')
134
- return Main.result_single_object(api_console.read("transfers/#{transfer_id}"))
134
+ return Result::SingleObject.new(api_console.read("transfers/#{transfer_id}"))
135
135
  when :files
136
136
  transfer_id = options.instance_identifier(description: 'transfer ID')
137
137
  query = query_read_delete(default: {})
138
138
  query['limit'] ||= 100
139
- return Main.result_object_list(api_console.read("transfers/#{transfer_id}/files", query))
139
+ return Result::ObjectList.new(api_console.read("transfers/#{transfer_id}/files", query))
140
140
  when :start, :pause, :cancel, :resume, :rerun, :change_rate, :change_policy, :move_forwards, :move_back
141
141
  transfer_id = options.instance_identifier(description: 'transfer ID')
142
- return Main.result_single_object(api_console.update("transfers/#{transfer_id}/#{command}", query_read_delete))
142
+ return Result::SingleObject.new(api_console.update("transfers/#{transfer_id}/#{command}", query_read_delete))
143
143
  end
144
144
  end
145
145
  end
@@ -36,11 +36,11 @@ module Aspera
36
36
  endpoint: options.get_option(:endpoint)
37
37
  }
38
38
  if service_credentials.nil?
39
- Aspera.assert(!cos_node_params[:endpoint].nil?, type: Cli::BadArgument){'endpoint required when service credentials not provided'}
39
+ Aspera.assert(!cos_node_params[:endpoint].nil?, 'endpoint required when service credentials not provided', type: Cli::BadArgument)
40
40
  cos_node_params[:api_key] = options.get_option(:apikey, mandatory: true)
41
41
  cos_node_params[:instance_id] = options.get_option(:crn, mandatory: true)
42
42
  else
43
- Aspera.assert(cos_node_params[:endpoint].nil?, type: Cli::BadArgument){'endpoint not allowed when service credentials provided'}
43
+ Aspera.assert(cos_node_params[:endpoint].nil?, 'endpoint not allowed when service credentials provided', type: Cli::BadArgument)
44
44
  cos_node_params.merge!(Api::CosNode.parameters_from_svc_credentials(service_credentials, options.get_option(:region, mandatory: true)))
45
45
  end
46
46
  api_node = Api::CosNode.new(**cos_node_params)
@@ -9,6 +9,9 @@ module Aspera
9
9
  module Cli
10
10
  # Instantiate plugin from well-known locations
11
11
  module Plugins
12
+ # @!method self.instance
13
+ # Returns the singleton instance of Factory
14
+ # @return [Factory] the singleton instance
12
15
  class Factory
13
16
  include Singleton
14
17
 
@@ -78,7 +78,7 @@ module Aspera
78
78
  # extract elements from faspex public link
79
79
  def get_link_data(public_url)
80
80
  public_uri = URI.parse(public_url)
81
- Aspera.assert(m = public_uri.path.match(%r{^(.*)/(external.*)$}), type: Cli::BadArgument){'Public link does not match Faspex format'}
81
+ Aspera.assert(m = public_uri.path.match(%r{^(.*)/(external.*)$}), 'Public link does not match Faspex format', type: Cli::BadArgument)
82
82
  base = m[1]
83
83
  subpath = m[2]
84
84
  port_add = public_uri.port.eql?(public_uri.default_port) ? '' : ":#{public_uri.port}"
@@ -165,7 +165,7 @@ module Aspera
165
165
  def mailbox_filtered_entries(stop_at_id: nil)
166
166
  recipient_names = [options.get_option(:recipient) || options.get_option(:username, mandatory: true)]
167
167
  # some workgroup messages have no star in recipient name
168
- recipient_names.push(recipient_names.first[1..-1]) if recipient_names.first.start_with?('*')
168
+ recipient_names.push(recipient_names.first.delete_prefix('*')) if recipient_names.first.start_with?('*')
169
169
  # mailbox is in ATOM_MAILBOXES
170
170
  mailbox = options.get_option(:box, mandatory: true)
171
171
  # parameters
@@ -176,7 +176,7 @@ module Aspera
176
176
  if !mailbox_query.nil?
177
177
  Aspera.assert_type(mailbox_query, Hash){'query'}
178
178
  Aspera.assert((mailbox_query.keys - ATOM_EXT_PARAMS).empty?){"query: supported params: #{ATOM_EXT_PARAMS}"}
179
- Aspera.assert(!(mailbox_query.key?('startIndex') && mailbox_query.key?('page'))){'query: startIndex and page are exclusive'}
179
+ Aspera.assert(!(mailbox_query.key?('startIndex') && mailbox_query.key?('page')), 'query: startIndex and page are exclusive')
180
180
  # Extract pagination control parameters (not part of API query)
181
181
  max_items = mailbox_query.delete(RestList::MAX_ITEMS)
182
182
  max_pages = mailbox_query.delete(RestList::MAX_PAGES)
@@ -286,15 +286,15 @@ module Aspera
286
286
  rescue StandardError => e
287
287
  nagios.add_critical('faspex api', e.to_s)
288
288
  end
289
- Main.result_object_list(nagios.status_list)
289
+ Result::ObjectList.new(nagios.status_list)
290
290
  when :package
291
291
  command_pkg = options.get_next_command(%i[send receive list show], aliases: {recv: :receive})
292
292
  case command_pkg
293
293
  when :show
294
294
  delivery_id = options.instance_identifier
295
- return Main.result_single_object(mailbox_filtered_entries(stop_at_id: delivery_id).find{ |p| p[PACKAGE_MATCH_FIELD].eql?(delivery_id)})
295
+ return Result::SingleObject.new(mailbox_filtered_entries(stop_at_id: delivery_id).find{ |p| p[PACKAGE_MATCH_FIELD].eql?(delivery_id)})
296
296
  when :list
297
- return Main.result_object_list(mailbox_filtered_entries, fields: [PACKAGE_MATCH_FIELD, 'title', 'items'])
297
+ return Result::ObjectList.new(mailbox_filtered_entries, fields: [PACKAGE_MATCH_FIELD, 'title', 'items'])
298
298
  when :send
299
299
  delivery_info = options.get_option(:delivery_info, mandatory: true)
300
300
  Aspera.assert_type(delivery_info, Hash, type: Cli::BadArgument){'delivery_info'}
@@ -308,7 +308,7 @@ module Aspera
308
308
  first_source['paths'].concat(transfer.source_list)
309
309
  source_id = options.get_option(:remote_source)
310
310
  if source_id && (m = Manager.percent_selector(source_id))
311
- Aspera.assert(m[:field].eql?('name'), type: Cli::BadArgument){'only name as selector, or give id'}
311
+ Aspera.assert_values(m[:field], ['name'], type: Cli::BadArgument){'selector field'}
312
312
  source_list = api_v3.read('source_shares')['items']
313
313
  source_id = self.class.get_source_id_by_name(m[:value], source_list)
314
314
  end
@@ -316,7 +316,7 @@ module Aspera
316
316
  pkg_created = api_v3.create('send', package_create_params)
317
317
  if first_source.key?('id')
318
318
  # no transfer spec if remote source: handled by faspex
319
- return {data: [pkg_created['links']['status']], type: :value_list, name: 'link'}
319
+ return Result::ValueList.new([pkg_created['links']['status']], name: 'link')
320
320
  end
321
321
  raise Cli::BadArgument, 'expecting one session exactly' if pkg_created['xfer_sessions'].length != 1
322
322
  transfer_spec = pkg_created['xfer_sessions'].first
@@ -326,7 +326,7 @@ module Aspera
326
326
  transfer_spec = send_public_link_to_ts(public_link_url, package_create_params)
327
327
  end
328
328
  # Log.dump(:transfer_spec,transfer_spec)
329
- return Main.result_transfer(transfer.start(transfer_spec))
329
+ return Runner.result_transfer(transfer.start(transfer_spec))
330
330
  when :receive
331
331
  link_url = options.get_option(:link)
332
332
  # list of faspex ID/URI to download
@@ -349,15 +349,15 @@ module Aspera
349
349
  end
350
350
  # get command line parameters
351
351
  delivery_id = options.instance_identifier
352
- Aspera.assert(!delivery_id.empty?){'empty id'}
352
+ Aspera.assert(!delivery_id.empty?, 'empty id')
353
353
  recipient = options.get_option(:recipient)
354
354
  if delivery_id.eql?(SpecialValues::ALL)
355
355
  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)}}
356
356
  elsif delivery_id.eql?(SpecialValues::INIT)
357
- Aspera.assert(skip_ids_persistency){'Only with option once_only'}
357
+ Aspera.assert(skip_ids_persistency, 'Only with option once_only')
358
358
  skip_ids_persistency.data.clear.concat(mailbox_filtered_entries.map{ |i| {id: i[PACKAGE_MATCH_FIELD]}})
359
359
  skip_ids_persistency.save
360
- return Main.result_status("Initialized skip for #{skip_ids_persistency.data.count} package(s)")
360
+ return Result::Status.new("Initialized skip for #{skip_ids_persistency.data.count} package(s)")
361
361
  elsif !recipient.nil? && recipient.start_with?('*')
362
362
  found_package_link = mailbox_filtered_entries(stop_at_id: delivery_id).find{ |p| p[PACKAGE_MATCH_FIELD].eql?(delivery_id)}['link'].first['href']
363
363
  raise "Not Found. Dropbox and Workgroup packages can use the link option with #{Transfer::Uri::SCHEME}" if found_package_link.nil?
@@ -401,7 +401,7 @@ module Aspera
401
401
  # skip_ids_data.select!{|id|pkg_id_uri.select{|p|p[:id].eql?(id)}}
402
402
  pkg_id_uri.reject!{ |i| skip_ids_data.include?(i[:id])}
403
403
  Log.dump(:pkg_id_uri, pkg_id_uri)
404
- return Main.result_status('no new package') if pkg_id_uri.empty?
404
+ return Result::Status.new('no new package') if pkg_id_uri.empty?
405
405
  result_transfer = []
406
406
  pkg_id_uri.each do |id_uri|
407
407
  if id_uri[:uri].nil?
@@ -427,22 +427,22 @@ module Aspera
427
427
  transfer_spec['direction'] = Transfer::Spec::DIRECTION_RECEIVE
428
428
  statuses = transfer.start(transfer_spec)
429
429
  end
430
- result_transfer.push({'package' => id_uri[:id], Main::STATUS_FIELD => statuses})
430
+ result_transfer.push({'package' => id_uri[:id], Runner::STATUS_FIELD => statuses})
431
431
  # skip only if all sessions completed
432
432
  skip_ids_data.push(id_uri[:id]) if TransferAgent.session_status(statuses).eql?(:success)
433
433
  end
434
434
  skip_ids_persistency&.save
435
- return Main.result_transfer_multiple(result_transfer)
435
+ return Runner.result_transfer_multiple(result_transfer)
436
436
  end
437
437
  when :source
438
438
  command_source = options.get_next_command(%i[list info node])
439
439
  source_list = api_v3.read('source_shares')['items']
440
440
  case command_source
441
441
  when :list
442
- return Main.result_object_list(source_list)
442
+ return Result::ObjectList.new(source_list)
443
443
  else # :info :node
444
444
  source_id = options.instance_identifier do |field, value|
445
- Aspera.assert(field.eql?('name'), type: Cli::BadArgument){'only name as selector, or give id'}
445
+ Aspera.assert_values(field, ['name'], type: Cli::BadArgument){'selector field'}
446
446
  self.class.get_source_id_by_name(value, source_list)
447
447
  end.to_i
448
448
  selected_source = source_list.find{ |i| i['id'].eql?(source_id)}
@@ -462,7 +462,7 @@ module Aspera
462
462
  Log.dump(:source_info, source_info)
463
463
  case command_source
464
464
  when :info
465
- return Main.result_single_object(source_info)
465
+ return Result::SingleObject.new(source_info)
466
466
  when :node
467
467
  node_config = ExtendedValue.instance.evaluate(source_info[KEY_NODE], context: 'faspex node')
468
468
  Log.log.debug{"node=#{node_config}"}
@@ -481,13 +481,13 @@ module Aspera
481
481
  end
482
482
  when :me
483
483
  my_info = api_v3.read('me')
484
- return Main.result_single_object(my_info)
484
+ return Result::SingleObject.new(my_info)
485
485
  when :dropbox
486
486
  command_pkg = options.get_next_command([:list])
487
487
  case command_pkg
488
488
  when :list
489
489
  dropbox_list = api_v3.read('dropboxes')
490
- return Main.result_object_list(dropbox_list['items'], fields: %w[name id description can_read can_write])
490
+ return Result::ObjectList.new(dropbox_list['items'], fields: %w[name id description can_read can_write])
491
491
  end
492
492
  when :v4
493
493
  command = options.get_next_command(%i[package dropbox dmembership workgroup wmembership user metadata_profile])
@@ -526,11 +526,11 @@ module Aspera
526
526
  u['first_name'], u['last_name'] = u['displayName'].split(' ', 2)
527
527
  u['x'] = true
528
528
  end
529
- return Main.result_object_list(users)
529
+ return Result::ObjectList.new(users)
530
530
  when :login_methods
531
531
  login_meths = api_v3.call(operation: 'GET', subpath: 'login/new', headers: {'Accept' => 'application/xrds+xml'}, ret: :resp).body
532
532
  login_methods = XmlSimple.xml_in(login_meths, {'ForceArray' => false})
533
- return Main.result_object_list(login_methods['XRD']['Service'])
533
+ return Result::ObjectList.new(login_methods['XRD']['Service'])
534
534
  end
535
535
  end
536
536
  end
@@ -213,10 +213,10 @@ module Aspera
213
213
  packages = []
214
214
  case package_ids
215
215
  when SpecialValues::INIT
216
- Aspera.assert(skip_ids_persistency){'Only with option once_only'}
216
+ Aspera.assert(skip_ids_persistency, 'Only with option once_only')
217
217
  skip_ids_persistency.data.clear.concat(list_packages_with_filter.first.map{ |p| p['id']})
218
218
  skip_ids_persistency.save
219
- return Main.result_status("Initialized skip for #{skip_ids_persistency.data.count} package(s)")
219
+ return Result::Status.new("Initialized skip for #{skip_ids_persistency.data.count} package(s)")
220
220
  when SpecialValues::ALL
221
221
  # TODO: if packages have same name, they will overwrite ?
222
222
  packages = list_packages_with_filter(query: {'status' => 'completed'}).first
@@ -234,8 +234,8 @@ module Aspera
234
234
  result_transfer = []
235
235
  param_file_list = {}
236
236
  begin
237
- param_file_list['paths'] = transfer.source_list.map{ |source| {'path'=>source}}
238
- rescue Cli::BadArgument
237
+ param_file_list['paths'] = transfer.ts_source_paths
238
+ rescue Cli::MissingArgument
239
239
  # paths is optional
240
240
  end
241
241
  box = options.get_option(:box)
@@ -259,18 +259,18 @@ module Aspera
259
259
  # delete flag for Connect Client
260
260
  transfer_spec.delete('authentication')
261
261
  statuses = transfer.start(transfer_spec)
262
- result_transfer.push({'package' => pkg_id, Main::STATUS_FIELD => statuses})
262
+ result_transfer.push({'package' => pkg_id, Runner::STATUS_FIELD => statuses})
263
263
  # skip only if all sessions completed
264
264
  if TransferAgent.session_status(statuses).eql?(:success) && skip_ids_persistency
265
265
  skip_ids_persistency.data.push(pkg_id)
266
266
  skip_ids_persistency.save
267
267
  end
268
268
  end
269
- return Main.result_transfer_multiple(result_transfer)
269
+ return Runner.result_transfer_multiple(result_transfer)
270
270
  end
271
271
 
272
272
  def package_send
273
- parameters = value_create_modify(command: :send)
273
+ parameters = value_create_modify(command: :send, schema: Schema::Registry.req_body(Schema::Registry::FASPEX, 'packages.post'))
274
274
  # autofill recipient for public url
275
275
  if @api_v5.pub_link_context&.key?('recipient_type') && !parameters.key?('recipients')
276
276
  parameters['recipients'] = [{
@@ -296,7 +296,7 @@ module Aspera
296
296
  )
297
297
  # well, we asked a TS for connect, but we actually want a generic one
298
298
  transfer_spec.delete('authentication')
299
- return Main.result_transfer(transfer.start(transfer_spec))
299
+ return Runner.result_transfer(transfer.start(transfer_spec))
300
300
  else
301
301
  # send from remote shared folder
302
302
  if (m = Manager.percent_selector(shared_folder))
@@ -314,7 +314,7 @@ module Aspera
314
314
  formatter.display_status("Package #{package['id']}")
315
315
  result = wait_package_status(package['id'])
316
316
  end
317
- return Main.result_single_object(result)
317
+ return Result::SingleObject.new(result)
318
318
  end
319
319
  end
320
320
 
@@ -371,24 +371,25 @@ module Aspera
371
371
  query.delete('iteration_token')
372
372
  end
373
373
  RestParameters.instance.spinner_cb.call(action: :success)
374
- return Main.result_object_list(all_items, total: total_count)
374
+ return Result::ObjectList.new(all_items, total: total_count)
375
375
  end
376
376
 
377
377
  def package_action
378
- command = options.get_next_command(%i[show browse status delete receive send list])
378
+ command = options.get_next_command(%i[show browse status delete receive send list file_processing])
379
379
  package_id =
380
- if %i[receive show browse status delete].include?(command)
380
+ unless %i[send list].include?(command)
381
381
  @api_v5.pub_link_context&.key?('package_id') ? @api_v5.pub_link_context['package_id'] : options.instance_identifier
382
382
  end
383
+ package_instance = "packages/#{package_id}"
383
384
  case command
384
385
  when :show
385
- return Main.result_single_object(@api_v5.read("packages/#{package_id}"))
386
+ return Result::SingleObject.new(@api_v5.read(package_instance))
386
387
  when :browse
387
- return browse_folder("packages/#{package_id}/files/#{Api::Faspex.box_type(options.get_option(:box))}", recipient_query(package_id))
388
+ return browse_folder("#{package_instance}/files/#{Api::Faspex.box_type(options.get_option(:box))}", recipient_query(package_id))
388
389
  when :status
389
390
  status_list = options.get_next_argument('list of states, or nothing', mandatory: false, validation: Array)
390
391
  status = wait_package_status(package_id, status_list: status_list)
391
- return Main.result_single_object(status)
392
+ return Result::SingleObject.new(status)
392
393
  when :delete
393
394
  ids = package_id
394
395
  ids = [ids] unless ids.is_a?(Array)
@@ -401,7 +402,7 @@ module Aspera
401
402
  body: {ids: ids},
402
403
  headers: {'Accept' => Mime::JSON}
403
404
  )
404
- return Main.result_status('Package(s) deleted')
405
+ return Result::Status.new('Package(s) deleted')
405
406
  when :receive
406
407
  return package_receive(package_id)
407
408
  when :send
@@ -411,11 +412,18 @@ module Aspera
411
412
  fields = %w[id title status sender.name recipients.0.name release_date total_bytes total_files]
412
413
  fields.delete('recipients.0.name') if %w[inbox inbox_history].include?(options.get_option(:box))
413
414
  fields.delete('sender.name') if %w[outbox outbox_history].include?(options.get_option(:box))
414
- return Main.result_object_list(list, total: total, fields: fields)
415
+ return Result::ObjectList.new(list, total: total, fields: fields)
416
+ when :file_processing
417
+ result, count = @api_v5.list_entities_limit_offset_total_count(
418
+ entity: "#{package_instance}/file_statuses",
419
+ items_key: 'files'
420
+ )
421
+ return Result::ObjectList.new(result, total: count)
415
422
  end
416
423
  end
417
424
 
418
425
  def execute_resource(res_sym)
426
+ # Arguments for Plugin::Base::entity_execute
419
427
  exec_args = {
420
428
  api: @api_v5,
421
429
  entity: res_sym.to_s
@@ -448,9 +456,14 @@ module Aspera
448
456
  available_commands += %i[shared_folders browse]
449
457
  when :jobs
450
458
  exec_args[:display_fields] = %w[id job_name job_type status]
459
+ when :file_processing
460
+ available_commands = %i[next modify]
461
+ # schema for modify
462
+ exec_args[:schema] = Schema::Registry.req_body(Schema::Registry::FASPEX, 'file_processing.put')
463
+ exec_args[:is_singleton] = true
451
464
  end
452
465
  res_command = options.get_next_command(available_commands)
453
- return Main.result_value_list(Api::Faspex::EMAIL_NOTIF_LIST, name: 'email_id') if res_command.eql?(:list) && res_sym.eql?(:email_notifications)
466
+ return Result::ValueList.new(Api::Faspex::EMAIL_NOTIF_LIST, name: 'email_id') if res_command.eql?(:list) && res_sym.eql?(:email_notifications)
454
467
  case res_command
455
468
  when :create, :modify, :delete, :show
456
469
  return entity_execute(command: res_command, **exec_args) do |field, value|
@@ -458,28 +471,28 @@ module Aspera
458
471
  end
459
472
  when :list
460
473
  data, total = exec_args[:api].list_entities_limit_offset_total_count(entity: exec_args[:entity], items_key: exec_args[:items_key], query: query_read_delete(default: exec_args[:list_query]))
461
- return Main.result_object_list(data, total: total, fields: exec_args[:display_fields])
474
+ return Result::ObjectList.new(data, total: total, fields: exec_args[:display_fields])
462
475
  when :shared_folders
463
476
  # nodes
464
477
  node_id = options.instance_identifier do |field, value|
465
478
  @api_v5.lookup_entity_by_field(entity: 'nodes', field: field, value: value)['id']
466
479
  end
467
- shfld_entity = "nodes/#{node_id}/shared_folders"
480
+ shared_folder_entity = "nodes/#{node_id}/shared_folders"
468
481
  sh_command = options.get_next_command(Operations::ALL + [:user])
469
482
  case sh_command
470
483
  when *Operations::ALL
471
484
  return entity_execute(
472
485
  api: @api_v5,
473
- entity: shfld_entity,
486
+ entity: shared_folder_entity,
474
487
  command: sh_command
475
488
  ) do |field, value|
476
- @api_v5.lookup_entity_by_field(entity: shfld_entity, field: field, value: value)['id']
489
+ @api_v5.lookup_entity_by_field(entity: shared_folder_entity, field: field, value: value)['id']
477
490
  end
478
491
  when :user
479
492
  sh_id = options.instance_identifier do |field, value|
480
- @api_v5.lookup_entity_by_field(entity: shfld_entity, field: field, value: value)['id']
493
+ @api_v5.lookup_entity_by_field(entity: shared_folder_entity, field: field, value: value)['id']
481
494
  end
482
- user_path = "#{shfld_entity}/#{sh_id}/custom_access_users"
495
+ user_path = "#{shared_folder_entity}/#{sh_id}/custom_access_users"
483
496
  return entity_execute(api: @api_v5, entity: user_path, items_key: 'users') do |field, value|
484
497
  @api_v5.lookup_entity_by_field(entity: user_path, items_key: 'users', field: field, value: value)['id']
485
498
  end
@@ -494,8 +507,7 @@ module Aspera
494
507
  when :invite_external_collaborator
495
508
  # :shared_inboxes, :workgroups
496
509
  shared_inbox_id = options.instance_identifier{ |field, value| @api_v5.lookup_entity_by_field(entity: res_sym.to_s, field: field, value: value, query: res_id_query)['id']}
497
- creation_payload = value_create_modify(command: res_command, type: [Hash, String])
498
- creation_payload = {'email_address' => creation_payload} if creation_payload.is_a?(String)
510
+ creation_payload = value_create_modify(command: res_command)
499
511
  result = @api_v5.create("#{res_sym}/#{shared_inbox_id}/external_collaborator", creation_payload)
500
512
  formatter.display_status(result['message'])
501
513
  result = @api_v5.lookup_entity_by_field(
@@ -504,7 +516,7 @@ module Aspera
504
516
  value: creation_payload['email_address'],
505
517
  query: {}
506
518
  )
507
- return Main.result_single_object(result)
519
+ return Result::SingleObject.new(result)
508
520
  when :members, :saml_groups
509
521
  # res_command := :shared_inboxes, :workgroups
510
522
  res_id = options.instance_identifier{ |field, value| @api_v5.lookup_entity_by_field(entity: res_sym.to_s, field: field, value: value, query: res_id_query)['id']}
@@ -550,7 +562,14 @@ module Aspera
550
562
  # :accounts
551
563
  contact_id = options.instance_identifier{ |field, value| @api_v5.lookup_entity_by_field(entity: 'accounts', field: field, value: value, query: res_id_query)['id']}
552
564
  @api_v5.create("accounts/#{contact_id}/reset_password", {})
553
- return Main.result_status('password reset, user shall check email')
565
+ return Result::Status.new('password reset, user shall check email')
566
+ when :next
567
+ result, count = @api_v5.list_entities_limit_offset_total_count(
568
+ entity: exec_args[:entity],
569
+ operation: 'POST',
570
+ items_key: 'files'
571
+ )
572
+ return Result::ObjectList.new(result, total: count)
554
573
  end
555
574
  Aspera.error_unreachable_line
556
575
  end
@@ -564,29 +583,29 @@ module Aspera
564
583
  delete_data = value_create_modify(command: command, default: {})
565
584
  delete_data = @api_v5.read('configuration').slice('days_before_deleting_package_records') if delete_data.empty?
566
585
  res = @api_v5.create('internal/packages/clean_deleted', delete_data)
567
- return Main.result_single_object(res)
586
+ return Result::SingleObject.new(res)
568
587
  when :events
569
588
  event_type = options.get_next_command(%i[application webhook])
570
589
  case event_type
571
590
  when :application
572
591
  list, total = @api_v5.list_entities_limit_offset_total_count(entity: 'application_events', query: query_read_delete)
573
- return Main.result_object_list(list, total: total, fields: %w[event_type created_at application user.name])
592
+ return Result::ObjectList.new(list, total: total, fields: %w[event_type created_at application user.name])
574
593
  when :webhook
575
594
  list, total = @api_v5.list_entities_limit_offset_total_count(
576
595
  entity: 'all_webhooks_events',
577
596
  query: query_read_delete,
578
597
  items_key: 'events'
579
598
  )
580
- return Main.result_object_list(list, total: total)
599
+ return Result::ObjectList.new(list, total: total)
581
600
  end
582
601
  when :configuration
583
602
  conf_path = 'configuration'
584
603
  conf_cmd = options.get_next_command(%i[show modify])
585
604
  case conf_cmd
586
605
  when :show
587
- return Main.result_single_object(@api_v5.read(conf_path))
606
+ return Result::SingleObject.new(@api_v5.read(conf_path))
588
607
  when :modify
589
- return Main.result_single_object(@api_v5.update(conf_path, value_create_modify(command: conf_cmd)))
608
+ return Result::SingleObject.new(@api_v5.update(conf_path, value_create_modify(command: conf_cmd)))
590
609
  end
591
610
  when :smtp
592
611
  # only one SMTP config
@@ -594,21 +613,21 @@ module Aspera
594
613
  smtp_cmd = options.get_next_command(%i[show create modify delete test])
595
614
  case smtp_cmd
596
615
  when :show
597
- return Main.result_single_object(@api_v5.read(smtp_path))
616
+ return Result::SingleObject.new(@api_v5.read(smtp_path))
598
617
  when :create
599
- return Main.result_single_object(@api_v5.create(smtp_path, value_create_modify(command: smtp_cmd)))
618
+ return Result::SingleObject.new(@api_v5.create(smtp_path, value_create_modify(command: smtp_cmd)))
600
619
  when :modify
601
- return Main.result_single_object(@api_v5.update(smtp_path, value_create_modify(command: smtp_cmd)))
620
+ return Result::SingleObject.new(@api_v5.update(smtp_path, value_create_modify(command: smtp_cmd)))
602
621
  when :delete
603
622
  @api_v5.delete(smtp_path)
604
- return Main.result_status('SMTP configuration deleted')
623
+ return Result::Status.new('SMTP configuration deleted')
605
624
  when :test
606
625
  test_data = options.get_next_argument('Email or test data, see API')
607
626
  test_data = {test_email_recipient: test_data} if test_data.is_a?(String)
608
627
  creation = @api_v5.create(File.join(smtp_path, 'test'), test_data)
609
628
  result = wait_for_job(creation['job_id'])
610
629
  result['serialized_args'] = JSON.parse(result['serialized_args']) rescue result['serialized_args']
611
- return Main.result_single_object(result)
630
+ return Result::SingleObject.new(result)
612
631
  end
613
632
  end
614
633
  end
@@ -625,7 +644,7 @@ module Aspera
625
644
  end
626
645
  case command
627
646
  when :version
628
- return Main.result_single_object(@api_v5.read('version'))
647
+ return Result::SingleObject.new(@api_v5.read('version'))
629
648
  when :health
630
649
  nagios = Nagios.new
631
650
  begin
@@ -638,29 +657,29 @@ module Aspera
638
657
  rescue StandardError => e
639
658
  nagios.add_critical('core', e.to_s)
640
659
  end
641
- Main.result_object_list(nagios.status_list)
660
+ Result::ObjectList.new(nagios.status_list)
642
661
  when :user
643
662
  case options.get_next_command(%i[account profile])
644
663
  when :account
645
- return Main.result_single_object(@api_v5.read('account', query_read_delete))
664
+ return Result::SingleObject.new(@api_v5.read('account', query_read_delete))
646
665
  when :profile
647
666
  case options.get_next_command(%i[show modify])
648
667
  when :show
649
- return Main.result_single_object(@api_v5.read('account/preferences'))
668
+ return Result::SingleObject.new(@api_v5.read('account/preferences'))
650
669
  when :modify
651
670
  @api_v5.update('account/preferences', options.get_next_argument('modified parameters', validation: Hash))
652
- return Main.result_status('modified')
671
+ return Result::Status.new('modified')
653
672
  end
654
673
  end
655
674
  when :bearer_token
656
- return Main.result_text(@api_v5.oauth.authorization)
675
+ return Result::Text.new(@api_v5.oauth.authorization)
657
676
  when :packages
658
677
  return package_action
659
678
  when :shared_folders
660
679
  all_shared_folders = @api_v5.read('shared_folders')['shared_folders']
661
680
  case options.get_next_command(%i[list browse])
662
681
  when :list
663
- return Main.result_object_list(all_shared_folders)
682
+ return Result::ObjectList.new(all_shared_folders)
664
683
  when :browse
665
684
  shared_folder_id = options.instance_identifier do |field, value|
666
685
  matches = all_shared_folders.select{ |i| i[field].eql?(value)}
@@ -685,7 +704,7 @@ module Aspera
685
704
  end
686
705
  when :resend
687
706
  @api_v5.create("#{invitation_endpoint}/#{options.instance_identifier}/resend", nil)
688
- return Main.result_status('Invitation resent')
707
+ return Result::Status.new('Invitation resent')
689
708
  else
690
709
  return entity_execute(
691
710
  api: @api_v5,
@@ -702,10 +721,10 @@ module Aspera
702
721
  parameters = value_create_modify(command: command, default: {}).symbolize_keys
703
722
  uri = URI.parse(parameters.delete(:url){WebServerSimple::DEFAULT_URL})
704
723
  server = WebServerSimple.new(uri, **parameters.slice(*WebServerSimple::PARAMS))
705
- Aspera.assert(parameters.except(*WebServerSimple::PARAMS).empty?)
724
+ Aspera.assert(parameters.except(*WebServerSimple::PARAMS).empty?){"unexpected parameters: #{parameters.except(*WebServerSimple::PARAMS).keys}"}
706
725
  server.mount(uri.path, Faspex4GWServlet, @api_v5, nil)
707
726
  server.start
708
- return Main.result_status('Gateway terminated')
727
+ return Result::Status.new('Gateway terminated')
709
728
  when :postprocessing
710
729
  require 'aspera/faspex_postproc' # cspell:disable-line
711
730
  parameters = value_create_modify(command: command, default: {}).symbolize_keys
@@ -714,7 +733,7 @@ module Aspera
714
733
  server = WebServerSimple.new(uri, **parameters.slice(*WebServerSimple::PARAMS))
715
734
  server.mount(uri.path, Faspex4PostProcServlet, parameters.except(*WebServerSimple::PARAMS))
716
735
  server.start
717
- return Main.result_status('Gateway terminated')
736
+ return Result::Status.new('Gateway terminated')
718
737
  end
719
738
  end
720
739
  SHARED_INBOX_MEMBER_LEVELS = %i[submit_only standard shared_inbox_admin].freeze
@@ -91,7 +91,7 @@ module Aspera
91
91
  rescue StandardError => e
92
92
  nagios.add_critical('api', e.to_s)
93
93
  end
94
- Main.result_object_list(nagios.status_list)
94
+ Result::ObjectList.new(nagios.status_list)
95
95
  when :bridges
96
96
  return entity_execute(api: api, entity: 'bridges')
97
97
  end
@@ -57,10 +57,10 @@ module Aspera
57
57
  rescue StandardError => e
58
58
  nagios.add_critical('api', e.to_s)
59
59
  end
60
- Main.result_object_list(nagios.status_list)
60
+ Result::ObjectList.new(nagios.status_list)
61
61
  when :info
62
62
  api_v1 = Api::Httpgw.new(url: base_url)
63
- return Main.result_single_object(api_v1.info)
63
+ return Result::SingleObject.new(api_v1.info)
64
64
  end
65
65
  end
66
66
  end