aspera-cli 4.17.0 → 4.18.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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -4
  3. data/CHANGELOG.md +23 -0
  4. data/CONTRIBUTING.md +15 -1
  5. data/README.md +620 -378
  6. data/bin/ascli +5 -0
  7. data/bin/asession +2 -2
  8. data/lib/aspera/agent/alpha.rb +6 -4
  9. data/lib/aspera/agent/base.rb +9 -6
  10. data/lib/aspera/agent/connect.rb +4 -4
  11. data/lib/aspera/agent/direct.rb +56 -37
  12. data/lib/aspera/agent/httpgw.rb +23 -324
  13. data/lib/aspera/agent/node.rb +19 -20
  14. data/lib/aspera/agent/trsdk.rb +19 -20
  15. data/lib/aspera/api/aoc.rb +17 -14
  16. data/lib/aspera/api/cos_node.rb +4 -4
  17. data/lib/aspera/api/httpgw.rb +339 -0
  18. data/lib/aspera/api/node.rb +34 -21
  19. data/lib/aspera/ascmd.rb +4 -3
  20. data/lib/aspera/ascp/installation.rb +15 -7
  21. data/lib/aspera/ascp/management.rb +2 -2
  22. data/lib/aspera/cli/basic_auth_plugin.rb +5 -9
  23. data/lib/aspera/cli/extended_value.rb +12 -6
  24. data/lib/aspera/cli/formatter.rb +155 -65
  25. data/lib/aspera/cli/hints.rb +18 -0
  26. data/lib/aspera/cli/main.rb +22 -29
  27. data/lib/aspera/cli/manager.rb +53 -36
  28. data/lib/aspera/cli/plugin.rb +26 -17
  29. data/lib/aspera/cli/plugin_factory.rb +31 -20
  30. data/lib/aspera/cli/plugins/alee.rb +14 -2
  31. data/lib/aspera/cli/plugins/aoc.rb +141 -131
  32. data/lib/aspera/cli/plugins/ats.rb +1 -1
  33. data/lib/aspera/cli/plugins/config.rb +52 -46
  34. data/lib/aspera/cli/plugins/console.rb +8 -5
  35. data/lib/aspera/cli/plugins/faspex.rb +27 -19
  36. data/lib/aspera/cli/plugins/faspex5.rb +222 -149
  37. data/lib/aspera/cli/plugins/faspio.rb +85 -0
  38. data/lib/aspera/cli/plugins/httpgw.rb +55 -0
  39. data/lib/aspera/cli/plugins/node.rb +86 -29
  40. data/lib/aspera/cli/plugins/orchestrator.rb +31 -29
  41. data/lib/aspera/cli/plugins/preview.rb +6 -2
  42. data/lib/aspera/cli/plugins/server.rb +5 -5
  43. data/lib/aspera/cli/plugins/shares.rb +16 -14
  44. data/lib/aspera/cli/sync_actions.rb +6 -6
  45. data/lib/aspera/cli/transfer_agent.rb +5 -4
  46. data/lib/aspera/cli/version.rb +1 -1
  47. data/lib/aspera/environment.rb +7 -6
  48. data/lib/aspera/faspex_gw.rb +5 -4
  49. data/lib/aspera/faspex_postproc.rb +2 -2
  50. data/lib/aspera/log.rb +6 -3
  51. data/lib/aspera/node_simulator.rb +2 -2
  52. data/lib/aspera/oauth/base.rb +31 -19
  53. data/lib/aspera/oauth/factory.rb +12 -13
  54. data/lib/aspera/oauth/generic.rb +1 -0
  55. data/lib/aspera/oauth/jwt.rb +18 -15
  56. data/lib/aspera/oauth/url_json.rb +8 -6
  57. data/lib/aspera/open_application.rb +5 -7
  58. data/lib/aspera/persistency_folder.rb +2 -2
  59. data/lib/aspera/preview/generator.rb +3 -3
  60. data/lib/aspera/preview/options.rb +3 -3
  61. data/lib/aspera/preview/terminal.rb +4 -4
  62. data/lib/aspera/preview/utils.rb +3 -3
  63. data/lib/aspera/proxy_auto_config.rb +5 -1
  64. data/lib/aspera/rest.rb +60 -74
  65. data/lib/aspera/rest_call_error.rb +1 -1
  66. data/lib/aspera/rest_error_analyzer.rb +2 -2
  67. data/lib/aspera/rest_errors_aspera.rb +1 -1
  68. data/lib/aspera/resumer.rb +1 -1
  69. data/lib/aspera/secret_hider.rb +2 -4
  70. data/lib/aspera/ssh.rb +1 -1
  71. data/lib/aspera/transfer/parameters.rb +39 -36
  72. data/lib/aspera/transfer/spec.rb +2 -0
  73. data/lib/aspera/transfer/sync.rb +2 -1
  74. data/lib/aspera/transfer/uri.rb +1 -1
  75. data/lib/aspera/uri_reader.rb +5 -4
  76. data/lib/aspera/web_auth.rb +1 -1
  77. data/lib/aspera/web_server_simple.rb +4 -3
  78. data.tar.gz.sig +0 -0
  79. metadata +5 -3
  80. metadata.gz.sig +0 -0
  81. data/lib/aspera/cli/plugins/bss.rb +0 -71
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aspera/rest'
4
+ require 'aspera/nagios'
5
+ require 'aspera/cli/basic_auth_plugin'
6
+
7
+ module Aspera
8
+ module Cli
9
+ module Plugins
10
+ class Faspio < BasicAuthPlugin
11
+ class << self
12
+ def application_name
13
+ 'faspio Gateway'
14
+ end
15
+
16
+ def detect(base_url)
17
+ api = Rest.new(base_url: base_url)
18
+ ping_result = api.read('ping')
19
+ server_type = ping_result[:http]['Server']
20
+ return nil unless ping_result[:data].is_a?(Hash) && ping_result[:data].empty?
21
+ return nil unless server_type.is_a?(String) && server_type.include?('faspio')
22
+ return {
23
+ version: server_type.gsub(%r{^.*/}, ''),
24
+ url: base_url
25
+ }
26
+ end
27
+ end
28
+ ACTIONS = %i[health bridges].freeze
29
+
30
+ def initialize(**env)
31
+ super
32
+ options.declare(:auth, 'OAuth type of authentication', values: %i[jwt basic])
33
+ options.declare(:client_id, 'OAuth client identifier')
34
+ options.declare(:private_key, 'OAuth JWT RSA private key PEM value (prefix file path with @file:)')
35
+ options.declare(:passphrase, 'OAuth JWT RSA private key passphrase')
36
+ options.parse_options!
37
+ end
38
+
39
+ def execute_action
40
+ base_url = options.get_option(:url, mandatory: true)
41
+ api =
42
+ case options.get_option(:auth, mandatory: true)
43
+ when :basic
44
+ basic_auth_api
45
+ when :jwt
46
+ app_client_id = options.get_option(:client_id, mandatory: true)
47
+ Rest.new(
48
+ base_url: base_url,
49
+ auth: {
50
+ type: :oauth2,
51
+ grant_method: :jwt,
52
+ base_url: "#{base_url}/auth",
53
+ client_id: app_client_id,
54
+ use_query: true,
55
+ payload: {
56
+ iss: app_client_id, # issuer
57
+ sub: app_client_id # subject
58
+ },
59
+ private_key_obj: OpenSSL::PKey::RSA.new(options.get_option(:private_key, mandatory: true), options.get_option(:passphrase)),
60
+ headers: {typ: 'JWT'}
61
+ })
62
+ end
63
+ command = options.get_next_command(ACTIONS)
64
+ case command
65
+ when :health
66
+ nagios = Nagios.new
67
+ begin
68
+ result = api.read('ping')[:data]
69
+ if result.is_a?(Hash) && result.empty?
70
+ nagios.add_ok('api', 'answered ok')
71
+ else
72
+ nagios.add_critical('api', 'not expected answer')
73
+ end
74
+ rescue StandardError => e
75
+ nagios.add_critical('api', e.to_s)
76
+ end
77
+ return nagios.result
78
+ when :bridges
79
+ return entity_action(api, 'bridges')
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aspera/rest'
4
+ require 'aspera/api/httpgw'
5
+ require 'aspera/nagios'
6
+
7
+ module Aspera
8
+ module Cli
9
+ module Plugins
10
+ class Httpgw < Plugin
11
+ class << self
12
+ def application_name
13
+ 'HTTP Gateway'
14
+ end
15
+
16
+ def detect(base_url)
17
+ api = Api::Httpgw.new(url: base_url)
18
+ api_info = api.info
19
+ return {
20
+ url: base_url,
21
+ version: api_info['version']
22
+ } if api_info.is_a?(Hash) && api_info.key?('download_endpoint')
23
+ return nil
24
+ end
25
+ end
26
+ ACTIONS = %i[health info].freeze
27
+
28
+ def initialize(**env)
29
+ super
30
+ options.declare(:url, 'URL of application, e.g. https://app.example.com/aspera/app')
31
+ options.parse_options!
32
+ end
33
+
34
+ def execute_action
35
+ base_url = options.get_option(:url, mandatory: true)
36
+ command = options.get_next_command(ACTIONS)
37
+ case command
38
+ when :health
39
+ nagios = Nagios.new
40
+ begin
41
+ Api::Httpgw.new(url: base_url)
42
+ nagios.add_ok('api', 'answered ok')
43
+ rescue StandardError => e
44
+ nagios.add_critical('api', e.to_s)
45
+ end
46
+ return nagios.result
47
+ when :info
48
+ api_v1 = Api::Httpgw.new(url: base_url)
49
+ return {type: :single_object, data: api_v1.info}
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -44,7 +44,8 @@ module Aspera
44
44
  next unless result[:http].body.eql?('')
45
45
  url_length = -2 - test_endpoint.length
46
46
  return {
47
- url: result[:http].uri.to_s[0..url_length]
47
+ url: result[:http].uri.to_s[0..url_length],
48
+ version: 'requires authentication'
48
49
  }
49
50
  rescue StandardError => e
50
51
  error = e
@@ -92,7 +93,7 @@ module Aspera
92
93
  SEARCH_REMOVE_FIELDS = %w[basename permissions].freeze
93
94
 
94
95
  # actions in execute_command_gen3
95
- COMMANDS_GEN3 = %i[search space mkdir mklink mkfile rename delete browse upload download http_node_download sync]
96
+ COMMANDS_GEN3 = %i[search space mkdir mklink mkfile rename delete browse upload download http_node_download sync transport]
96
97
 
97
98
  BASE_ACTIONS = %i[api_details].concat(COMMANDS_GEN3).freeze
98
99
 
@@ -187,6 +188,68 @@ module Aspera
187
188
  raise StandardError, 'expect: nil, String or Array'
188
189
  end
189
190
 
191
+ # directory: node, container: shares
192
+ FOLDER_TYPE = %w[directory container].freeze
193
+
194
+ def browse_gen3(prefix_path)
195
+ folders_to_process = [get_next_arg_add_prefix(prefix_path, 'path')]
196
+ query = options.get_option(:query, default: {})
197
+ # special parameter: max number of entries in result
198
+ max_items = query.delete('max')
199
+ # special parameter: recursive browsing
200
+ recursive = query.delete('recursive')
201
+ # special parameter: only return one entry for the path, even if folder
202
+ only_path = query.delete('self')
203
+ # allow user to specify a single call, and not recursive
204
+ single_call = query.key?('skip')
205
+ # API default is 100, so use 1000 for default
206
+ query['count'] ||= 1000
207
+ raise Cli::BadArgument, 'options recursive and skip cannot be used together' if recursive && single_call
208
+ all_items = []
209
+ until folders_to_process.empty?
210
+ path = folders_to_process.shift
211
+ query['path'] = path
212
+ offset = 0
213
+ total_count = nil
214
+ result = nil
215
+ loop do
216
+ # example: send_result={'items'=>[{'file'=>"filename1","permissions"=>[{'name'=>'read'},{'name'=>'write'}]}]}
217
+ response = @api_node.call(
218
+ operation: 'POST',
219
+ subpath: 'files/browse',
220
+ headers: {'Accept' => 'application/json'},
221
+ body: query,
222
+ body_type: :json)
223
+ # 'file','symbolic_link'
224
+ if only_path || !FOLDER_TYPE.include?(response[:data]['self']['type'])
225
+ result = { type: :single_object, data: response[:data]['self']}
226
+ break
227
+ end
228
+ items = response[:data]['items']
229
+ total_count ||= response[:data]['total_count']
230
+ all_items.concat(items)
231
+ if single_call
232
+ formatter.display_item_count(response[:data]['item_count'], total_count)
233
+ break
234
+ end
235
+ if recursive
236
+ folders_to_process.concat(items.select{|i|FOLDER_TYPE.include?(i['type'])}.map{|i|i['path']})
237
+ end
238
+ if !max_items.nil? && (all_items.count >= max_items)
239
+ all_items = all_items.slice(0, max_items) if all_items.count > max_items
240
+ break
241
+ end
242
+ break if all_items.count >= total_count
243
+ offset += items.count
244
+ query['skip'] = offset
245
+ formatter.long_operation_running(all_items.count)
246
+ end
247
+ query.delete('skip')
248
+ end
249
+ result ||= {type: :object_list, data: all_items}
250
+ return c_result_remove_prefix_path(result, 'path', prefix_path)
251
+ end
252
+
190
253
  # file and folder related commands
191
254
  def execute_command_gen3(command, prefix_path)
192
255
  case command
@@ -235,20 +298,7 @@ module Aspera
235
298
  resp = @api_node.create('files/rename', { 'paths' => [{ 'path' => path_base, 'source' => path_src, 'destination' => path_dst }] })
236
299
  return c_result_translate_rem_prefix(resp, 'entry', 'moved', prefix_path)
237
300
  when :browse
238
- query = { path: get_next_arg_add_prefix(prefix_path, 'path')}
239
- additional_query = options.get_option(:query)
240
- query.merge!(additional_query) unless additional_query.nil?
241
- send_result = @api_node.create('files/browse', query)[:data]
242
- # example: send_result={'items'=>[{'file'=>"filename1","permissions"=>[{'name'=>'read'},{'name'=>'write'}]}]}
243
- # if there is no items
244
- case send_result['self']['type']
245
- when 'directory', 'container' # directory: node, container: shares
246
- result = { data: send_result['items'], type: :object_list }
247
- formatter.display_item_count(send_result['item_count'], send_result['total_count'])
248
- else # 'file','symbolic_link'
249
- result = { data: send_result['self'], type: :single_object}
250
- end
251
- return c_result_remove_prefix_path(result, 'path', prefix_path)
301
+ return browse_gen3(prefix_path)
252
302
  when :sync
253
303
  return execute_sync_action do |sync_direction, local_path, remote_path|
254
304
  # Gen3 API
@@ -303,6 +353,8 @@ module Aspera
303
353
  subpath: "files/#{URI.encode_www_form_component(remote_path)}/contents",
304
354
  save_to_file: File.join(transfer.destination_folder(Transfer::Spec::DIRECTION_RECEIVE), file_name))
305
355
  return Main.result_status("downloaded: #{file_name}")
356
+ when :transport
357
+ return {type: :single_object, data: @api_node.transport_params}
306
358
  end
307
359
  Aspera.error_unreachable_line
308
360
  end
@@ -358,9 +410,10 @@ module Aspera
358
410
  begin
359
411
  @api_node.call(
360
412
  operation: 'POST',
361
- subpath: 'services/soap/Transfer-201210',
362
- headers: {'Content-Type' => 'text/xml;charset=UTF-8', 'SOAPAction' => 'FASPSessionNET-200911#GetSessionInfo'},
363
- text_body_params: CENTRAL_SOAP_API_TEST)[:http].body
413
+ subpath: 'services/soap/Transfer-201210',
414
+ headers: {'Content-Type' => 'text/xml;charset=UTF-8', 'SOAPAction' => 'FASPSessionNET-200911#GetSessionInfo'},
415
+ body: CENTRAL_SOAP_API_TEST,
416
+ body_type: :text)[:http].body
364
417
  nagios.add_ok('central', 'accessible by node')
365
418
  rescue StandardError => e
366
419
  nagios.add_critical('central', e.to_s)
@@ -420,7 +473,7 @@ module Aspera
420
473
  result[:password] = apifid[:api].auth_params[:password]
421
474
  when :oauth2
422
475
  result[:username] = apifid[:api].params[:headers][Api::Node::HEADER_X_ASPERA_ACCESS_KEY]
423
- result[:password] = apifid[:api].oauth_token
476
+ result[:password] = apifid[:api].oauth.token
424
477
  else Aspera.error_unreachable_line
425
478
  end
426
479
  return {type: :single_object, data: result} if command_repo.eql?(:node_info)
@@ -431,7 +484,7 @@ module Aspera
431
484
  apifid = @api_node.resolve_api_fid(top_file_id, options.get_next_argument('path'))
432
485
  file_info = apifid[:api].read("files/#{apifid[:file_id]}")[:data]
433
486
  if file_info['type'].eql?('folder')
434
- result = apifid[:api].read("files/#{apifid[:file_id]}/files", old_query_read_delete)
487
+ result = apifid[:api].read("files/#{apifid[:file_id]}/files", query_read_delete)
435
488
  items = result[:data]
436
489
  formatter.display_item_count(result[:data].length, result[:http]['X-Total-Count'])
437
490
  else
@@ -538,7 +591,7 @@ module Aspera
538
591
  subpath: "files/#{apifid[:file_id]}/preview",
539
592
  headers: {'Accept' => 'image/png'}
540
593
  )
541
- return Main.result_picture_in_terminal(options, result[:http].body)
594
+ return Main.result_image(result[:http].body, formatter: formatter)
542
595
  when :permission
543
596
  apifid = apifid_from_next_arg(top_file_id)
544
597
  command_perm = options.get_next_command(%i[list create delete])
@@ -574,9 +627,9 @@ module Aspera
574
627
  else Aspera.error_unreachable_line
575
628
  end
576
629
  else Aspera.error_unreachable_line
577
- end # command_repo
630
+ end
578
631
  Aspera.error_unreachable_line
579
- end # execute_command_gen4
632
+ end
580
633
 
581
634
  # This is older API
582
635
  def execute_async
@@ -695,11 +748,15 @@ module Aspera
695
748
  when *Plugin::ALL_OPS then return entity_command(sync_command, @api_node, 'asyncs', item_list_key: 'ids'){|field, value|ssync_lookup(field, value)}
696
749
  else
697
750
  asyncs_id = instance_identifier {|field, value|ssync_lookup(field, value)}
698
- parameters = nil
699
751
  if %i[start stop].include?(sync_command)
700
- @api_node.create("asyncs/#{asyncs_id}/#{sync_command}", parameters)
752
+ @api_node.call(
753
+ operation: 'POST',
754
+ subpath: "asyncs/#{asyncs_id}/#{sync_command}",
755
+ body: '',
756
+ body_type: :text)[:http].body
701
757
  return Main.result_status('Done')
702
758
  end
759
+ parameters = nil
703
760
  parameters = query_option(default: {}) if %i[bandwidth counters files].include?(sync_command)
704
761
  return { type: :single_object, data: @api_node.read("asyncs/#{asyncs_id}/#{sync_command}", parameters)[:data] }
705
762
  end
@@ -707,7 +764,7 @@ module Aspera
707
764
  command = options.get_next_command(%i[list create show modify cancel])
708
765
  case command
709
766
  when :list
710
- resp = @api_node.read('ops/transfers', old_query_read_delete)
767
+ resp = @api_node.read('ops/transfers', query_read_delete)
711
768
  return { type: :object_list, data: resp[:data], fields: %w[id status] } # TODO: useful?
712
769
  when :create
713
770
  resp = @api_node.create('streams', value_create_modify(command: command))
@@ -841,7 +898,7 @@ module Aspera
841
898
  resp = @api_node.create(res_class_path, value_create_modify(command: command))
842
899
  return Main.result_status("#{resp[:data]['id']} created")
843
900
  when :list
844
- resp = @api_node.read(res_class_path, old_query_read_delete)
901
+ resp = @api_node.read(res_class_path, query_read_delete)
845
902
  return { type: :value_list, data: resp[:data]['ids'], name: 'id' }
846
903
  when :show
847
904
  return { type: :single_object, data: @api_node.read(one_res_path)[:data]}
@@ -914,7 +971,7 @@ module Aspera
914
971
  server.mount(uri.path, NodeSimulatorServlet, parameters[:credentials], transfer)
915
972
  server.start
916
973
  return Main.result_status('Simulator terminated')
917
- end # case command
974
+ end
918
975
  raise 'ERROR: shall not reach this line'
919
976
  end
920
977
  end
@@ -60,33 +60,37 @@ module Aspera
60
60
 
61
61
  ACTIONS = %i[health info workflow plugins processes].freeze
62
62
 
63
- def call_ao(endpoint, opt={})
64
- opt[:prefix] = 'api' unless opt.key?(:prefix)
63
+ # call orchestrator api
64
+ # @param endpoint [String] the endpoint to call
65
+ # @param prefix [String] the prefix to add to the endpoint
66
+ # @param id [String] the id to add to the endpoint
67
+ # @param ret_style [Symbol] the return style, :header, :arg, :ext(extension)
68
+ # @param format [String] the format to request, 'json', 'xml', nil
69
+ # @param args [Hash] the arguments to pass
70
+ # @param xml_arrays [Boolean] if true, force arrays in xml parsing
71
+ def call_ao(endpoint, prefix: 'api', id: nil, ret_style: nil, format: 'json', args: nil, xml_arrays: true)
65
72
  # calls are GET
66
73
  call_args = {operation: 'GET', subpath: endpoint}
67
74
  # specify prefix if necessary
68
- call_args[:subpath] = "#{opt[:prefix]}/#{call_args[:subpath]}" unless opt[:prefix].nil?
75
+ call_args[:subpath] = "#{prefix}/#{call_args[:subpath]}" unless prefix.nil?
69
76
  # specify id if necessary
70
- call_args[:subpath] = "#{call_args[:subpath]}/#{opt[:id]}" if opt.key?(:id)
71
- call_type = options.get_option(:ret_style, mandatory: true)
72
- call_type = opt[:ret_style] if opt.key?(:ret_style)
73
- format = 'json'
74
- format = opt[:format] if opt.key?(:format)
75
- call_args[:url_params] = opt[:args] unless opt[:args].nil?
77
+ call_args[:subpath] = "#{call_args[:subpath]}/#{id}" unless id.nil?
78
+ ret_style = options.get_option(:ret_style, mandatory: true) if ret_style.nil?
79
+ call_args[:query] = args unless args.nil?
76
80
  unless format.nil?
77
- case call_type
81
+ case ret_style
78
82
  when :header
79
83
  call_args[:headers] = {'Accept' => "application/#{format}" }
80
84
  when :arg
81
- call_args[:url_params] ||= {}
82
- call_args[:url_params][:format] = format
85
+ call_args[:query] ||= {}
86
+ call_args[:query][:format] = format
83
87
  when :ext
84
88
  call_args[:subpath] = "#{call_args[:subpath]}.#{format}"
85
- else Aspera.error_unexpected_value(call_type)
89
+ else Aspera.error_unexpected_value(ret_style)
86
90
  end
87
91
  end
88
92
  result = @api_orch.call(**call_args)
89
- result[:data] = XmlSimple.xml_in(result[:http].body, opt[:xml_opt] || {'ForceArray' => true}) if format.eql?('xml')
93
+ result[:data] = XmlSimple.xml_in(result[:http].body, {'ForceArray' => xml_arrays}) if format.eql?('xml')
90
94
  Log.log.debug{Log.dump(:data, result[:data])}
91
95
  return result
92
96
  end
@@ -121,7 +125,7 @@ module Aspera
121
125
  when :health
122
126
  nagios = Nagios.new
123
127
  begin
124
- info = call_ao('remote_node_ping', format: 'xml', xml_opt: {'ForceArray' => false})[:data]
128
+ info = call_ao('remote_node_ping', format: 'xml', xml_arrays: false)[:data]
125
129
  nagios.add_ok('api', 'accessible')
126
130
  nagios.check_product_version('api', 'orchestrator', info['orchestrator-version'])
127
131
  rescue StandardError => e
@@ -129,7 +133,7 @@ module Aspera
129
133
  end
130
134
  return nagios.result
131
135
  when :info
132
- result = call_ao('remote_node_ping', format: 'xml', xml_opt: {'ForceArray' => false})[:data]
136
+ result = call_ao('remote_node_ping', format: 'xml', xml_arrays: false)[:data]
133
137
  return {type: :single_object, data: result}
134
138
  when :processes
135
139
  # TODO: Bug ? API has only XML format
@@ -146,9 +150,8 @@ module Aspera
146
150
  end
147
151
  case command
148
152
  when :status
149
- call_opts = {}
150
- call_opts[:id] = wf_id unless wf_id.eql?(ExtendedValue::ALL)
151
- result = call_ao('workflows_status', call_opts)[:data]
153
+ wf_id = nil if wf_id.eql?(ExtendedValue::ALL)
154
+ result = call_ao('workflows_status', id: wf_id)[:data]
152
155
  return {type: :object_list, data: result['workflows']['workflow']}
153
156
  when :list
154
157
  result = call_ao('workflows_list', id: 0)[:data]
@@ -172,7 +175,6 @@ module Aspera
172
175
  data: nil
173
176
  }
174
177
  call_params = {format: :json}
175
- override_accept = nil
176
178
  # get external parameters if any
177
179
  options.get_next_argument('external_parameters', mandatory: false, type: Hash, default: {}).each do |name, value|
178
180
  call_params["external_parameters[#{name}]"] = value
@@ -192,15 +194,15 @@ module Aspera
192
194
  end
193
195
  if call_params['synchronous']
194
196
  result[:type] = :text
195
- override_accept = 'text/plain'
196
197
  end
197
- result[:data] = call_ao('initiate', id: wf_id, args: call_params, accept: override_accept)[:data]
198
+ result[:data] = call_ao('initiate', id: wf_id, args: call_params)[:data]
198
199
  return result
199
- end # wf command
200
+ end
200
201
  else Aspera.error_unexpected_value(command)
201
- end # case command
202
- end # execute_action
203
- end # Orchestrator
204
- end # Plugins
205
- end # Cli
206
- end # Aspera
202
+ end
203
+ end
204
+ private :call_ao
205
+ end
206
+ end
207
+ end
208
+ end
@@ -128,7 +128,11 @@ module Aspera
128
128
  def get_folder_entries(file_id, request_args=nil)
129
129
  headers = {'Accept' => 'application/json'}
130
130
  headers['X-Aspera-Cache-Control'] = 'no-cache' if @option_folder_reset_cache.eql?(:header)
131
- return @api_node.call(operation: 'GET', subpath: "files/#{file_id}/files", headers: headers, url_params: request_args)[:data]
131
+ return @api_node.call(
132
+ operation: 'GET',
133
+ subpath: "files/#{file_id}/files",
134
+ headers: headers,
135
+ query: request_args)[:data]
132
136
  # return @api_node.read("files/#{file_id}/files",request_args)[:data]
133
137
  end
134
138
 
@@ -338,7 +342,7 @@ module Aspera
338
342
  rescue StandardError => e
339
343
  Log.log.error{"Ignore: #{e.message}"}
340
344
  Log.log.debug(e.backtrace.join("\n").red)
341
- end # generate_preview
345
+ end
342
346
 
343
347
  # scan all files in provided folder entry
344
348
  # @param top_path subpath to start folder scan inside
@@ -251,8 +251,8 @@ module Aspera
251
251
  end
252
252
  else Aspera.error_unreachable_line
253
253
  end
254
- end # execute_action
255
- end # Server
256
- end # Plugins
257
- end # Cli
258
- end # Aspera
254
+ end
255
+ end
256
+ end
257
+ end
258
+ end
@@ -7,7 +7,7 @@ module Aspera
7
7
  module Plugins
8
8
  # Plugin for Aspera Shares v1
9
9
  class Shares < Cli::BasicAuthPlugin
10
- API_BASE = 'node_api'
10
+ NODE_API_PREFIX = 'node_api'
11
11
  class << self
12
12
  def detect(address_or_url)
13
13
  address_or_url = "https://#{address_or_url}" unless address_or_url.match?(%r{^[a-z]{1,6}://})
@@ -16,7 +16,7 @@ module Aspera
16
16
  begin
17
17
  # shall fail: shares requires auth, but we check error message
18
18
  # TODO: use ping instead ?
19
- api.read("#{API_BASE}/app")
19
+ api.read("#{NODE_API_PREFIX}/app")
20
20
  rescue RestCallError => e
21
21
  if e.response.code.to_s.eql?('401') && e.response.body.eql?('{"error":{"user_message":"API user authentication failed"}}')
22
22
  found = true
@@ -64,22 +64,24 @@ module Aspera
64
64
  when :health
65
65
  nagios = Nagios.new
66
66
  begin
67
- Rest
68
- .new(base_url: "#{options.get_option(:url, mandatory: true)}/#{API_BASE}")
67
+ res = Rest
68
+ .new(base_url: "#{options.get_option(:url, mandatory: true)}/#{NODE_API_PREFIX}")
69
69
  .call(
70
70
  operation: 'GET',
71
71
  subpath: 'ping',
72
- headers: {'content-type': 'application/json'},
73
- return_error: true)
72
+ headers: {'content-type': 'application/json'})
73
+ raise 'Shares not detected' unless res[:http].body.eql?(' ')
74
74
  nagios.add_ok('shares api', 'accessible')
75
75
  rescue StandardError => e
76
- nagios.add_critical('node api', e.to_s)
76
+ nagios.add_critical('API', e.to_s)
77
77
  end
78
78
  return nagios.result
79
79
  when :repository, :files
80
- api_shares_node = basic_auth_api(API_BASE)
80
+ api_shares_node = basic_auth_api(NODE_API_PREFIX)
81
81
  repo_command = options.get_next_command(Node::COMMANDS_SHARES)
82
- return Node.new(**init_params, api: api_shares_node).execute_action(repo_command)
82
+ return Node
83
+ .new(**init_params, api: api_shares_node)
84
+ .execute_action(repo_command)
83
85
  when :admin
84
86
  api_shares_admin = basic_auth_api('api/v1')
85
87
  admin_command = options.get_next_command(%i[node share transfer_settings user group].freeze)
@@ -150,8 +152,8 @@ module Aspera
150
152
  end
151
153
  end
152
154
  end
153
- end # execute action
154
- end # Shares
155
- end # Plugins
156
- end # Cli
157
- end # Aspera
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
@@ -60,9 +60,9 @@ module Aspera
60
60
  sync_session_name = options.get_next_argument('name of sync session', mandatory: false, type: String)
61
61
  async_params = options.get_option(:sync_info, mandatory: true)
62
62
  return {type: :single_object, data: Transfer::Sync.admin_status(async_params, sync_session_name)}
63
- end # command2
64
- end # command
65
- end # execute_action
66
- end # SyncActions
67
- end # Cli
68
- end # Aspera
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -26,6 +26,7 @@ module Aspera
26
26
 
27
27
  <%=ts.to_yaml%>
28
28
  END_OF_TEMPLATE
29
+ CP4I_REMOTE_HOST_LB = 'N/A'
29
30
  # % (formatting bug in eclipse)
30
31
  private_constant :FILE_LIST_FROM_ARGS,
31
32
  :FILE_LIST_FROM_TRANSFER_SPEC,
@@ -101,8 +102,6 @@ module Aspera
101
102
  def agent_instance
102
103
  return @agent unless @agent.nil?
103
104
  agent_type = @opt_mgr.get_option(:transfer, mandatory: true)
104
- # agent plugin is loaded on demand to avoid loading unnecessary dependencies
105
- require "aspera/agent/#{agent_type}"
106
105
  # set keys as symbols
107
106
  agent_options = @opt_mgr.get_option(:transfer_info).symbolize_keys
108
107
  # special cases
@@ -126,8 +125,7 @@ module Aspera
126
125
  end
127
126
  agent_options[:progress] = @config.progress_bar
128
127
  # get agent instance
129
- new_agent = Kernel.const_get("Aspera::Agent::#{agent_type.capitalize}").new(agent_options)
130
- self.agent_instance = new_agent
128
+ self.agent_instance = Agent::Base.factory_create(agent_type, agent_options)
131
129
  Log.log.debug{"transfer agent is a #{@agent.class}"}
132
130
  return @agent
133
131
  end
@@ -218,6 +216,9 @@ module Aspera
218
216
  def start(transfer_spec, rest_token: nil)
219
217
  # check parameters
220
218
  Aspera.assert_type(transfer_spec, Hash){'transfer_spec'}
219
+ if transfer_spec['remote_host'].eql?(CP4I_REMOTE_HOST_LB)
220
+ raise "Wrong remote host: #{CP4I_REMOTE_HOST_LB}"
221
+ end
221
222
  # process :src option
222
223
  case transfer_spec['direction']
223
224
  when Transfer::Spec::DIRECTION_RECEIVE
@@ -4,6 +4,6 @@ module Aspera
4
4
  module Cli
5
5
  # for beta add extension : .beta1
6
6
  # for dev version add extension : .pre
7
- VERSION = '4.17.0'
7
+ VERSION = '4.18.0'
8
8
  end
9
9
  end
@@ -27,6 +27,7 @@ module Aspera
27
27
  BYTES_PER_MEBIBIT = MEBI / BITS_PER_BYTE
28
28
 
29
29
  class << self
30
+ @terminal_supports_unicode = nil
30
31
  def ruby_version
31
32
  return RbConfig::CONFIG['RUBY_PROGRAM_VERSION']
32
33
  end
@@ -121,10 +122,10 @@ module Aspera
121
122
  end
122
123
 
123
124
  # @return true if we can display Unicode characters
124
- def use_unicode?
125
- @use_unicode = terminal? && ENV.values_at('LC_ALL', 'LC_CTYPE', 'LANG').compact.first.include?('UTF-8') if @use_unicode.nil?
126
- return @use_unicode
125
+ def terminal_supports_unicode?
126
+ @terminal_supports_unicode = terminal? && ENV.values_at('LC_ALL', 'LC_CTYPE', 'LANG').compact.first.include?('UTF-8') if @terminal_supports_unicode.nil?
127
+ return @terminal_supports_unicode
127
128
  end
128
- end # self
129
- end # Environment
130
- end # Aspera
129
+ end
130
+ end
131
+ end