aspera-cli 4.16.0 → 4.17.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 (97) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +50 -19
  4. data/CONTRIBUTING.md +3 -1
  5. data/README.md +965 -793
  6. data/bin/asession +29 -21
  7. data/lib/aspera/{fasp/agent_alpha.rb → agent/alpha.rb} +26 -25
  8. data/lib/aspera/{fasp/agent_base.rb → agent/base.rb} +15 -12
  9. data/lib/aspera/{fasp/agent_connect.rb → agent/connect.rb} +13 -11
  10. data/lib/aspera/{fasp/agent_direct.rb → agent/direct.rb} +49 -53
  11. data/lib/aspera/{fasp/agent_httpgw.rb → agent/httpgw.rb} +20 -19
  12. data/lib/aspera/{fasp/agent_node.rb → agent/node.rb} +20 -33
  13. data/lib/aspera/{fasp/agent_trsdk.rb → agent/trsdk.rb} +11 -11
  14. data/lib/aspera/api/aoc.rb +586 -0
  15. data/lib/aspera/api/ats.rb +46 -0
  16. data/lib/aspera/api/cos_node.rb +95 -0
  17. data/lib/aspera/api/node.rb +344 -0
  18. data/lib/aspera/ascmd.rb +46 -10
  19. data/lib/aspera/{fasp → ascp}/installation.rb +5 -5
  20. data/lib/aspera/{fasp → ascp}/management.rb +3 -8
  21. data/lib/aspera/{fasp → ascp}/products.rb +1 -1
  22. data/lib/aspera/assert.rb +30 -30
  23. data/lib/aspera/cli/basic_auth_plugin.rb +11 -10
  24. data/lib/aspera/cli/extended_value.rb +1 -1
  25. data/lib/aspera/cli/formatter.rb +13 -13
  26. data/lib/aspera/cli/hints.rb +5 -5
  27. data/lib/aspera/cli/main.rb +35 -28
  28. data/lib/aspera/cli/manager.rb +25 -24
  29. data/lib/aspera/cli/plugin.rb +22 -15
  30. data/lib/aspera/cli/plugin_factory.rb +61 -0
  31. data/lib/aspera/cli/plugins/alee.rb +7 -7
  32. data/lib/aspera/cli/plugins/aoc.rb +83 -77
  33. data/lib/aspera/cli/plugins/ats.rb +32 -33
  34. data/lib/aspera/cli/plugins/bss.rb +3 -4
  35. data/lib/aspera/cli/plugins/config.rb +169 -186
  36. data/lib/aspera/cli/plugins/console.rb +8 -6
  37. data/lib/aspera/cli/plugins/cos.rb +19 -18
  38. data/lib/aspera/cli/plugins/faspex.rb +61 -54
  39. data/lib/aspera/cli/plugins/faspex5.rb +150 -103
  40. data/lib/aspera/cli/plugins/node.rb +68 -73
  41. data/lib/aspera/cli/plugins/orchestrator.rb +34 -44
  42. data/lib/aspera/cli/plugins/preview.rb +31 -31
  43. data/lib/aspera/cli/plugins/server.rb +31 -33
  44. data/lib/aspera/cli/plugins/shares.rb +13 -11
  45. data/lib/aspera/cli/sync_actions.rb +8 -8
  46. data/lib/aspera/cli/transfer_agent.rb +32 -19
  47. data/lib/aspera/cli/transfer_progress.rb +1 -1
  48. data/lib/aspera/cli/version.rb +1 -1
  49. data/lib/aspera/colors.rb +5 -0
  50. data/lib/aspera/command_line_builder.rb +14 -14
  51. data/lib/aspera/coverage.rb +1 -2
  52. data/lib/aspera/data_repository.rb +1 -1
  53. data/lib/aspera/environment.rb +2 -3
  54. data/lib/aspera/faspex_gw.rb +5 -6
  55. data/lib/aspera/faspex_postproc.rb +1 -1
  56. data/lib/aspera/id_generator.rb +2 -2
  57. data/lib/aspera/json_rpc.rb +5 -5
  58. data/lib/aspera/keychain/encrypted_hash.rb +6 -6
  59. data/lib/aspera/keychain/macos_security.rb +27 -22
  60. data/lib/aspera/log.rb +2 -2
  61. data/lib/aspera/nagios.rb +3 -3
  62. data/lib/aspera/node_simulator.rb +5 -6
  63. data/lib/aspera/oauth/base.rb +143 -0
  64. data/lib/aspera/oauth/factory.rb +124 -0
  65. data/lib/aspera/oauth/generic.rb +34 -0
  66. data/lib/aspera/oauth/jwt.rb +51 -0
  67. data/lib/aspera/oauth/url_json.rb +31 -0
  68. data/lib/aspera/oauth/web.rb +50 -0
  69. data/lib/aspera/oauth.rb +5 -331
  70. data/lib/aspera/open_application.rb +7 -7
  71. data/lib/aspera/persistency_action_once.rb +4 -4
  72. data/lib/aspera/persistency_folder.rb +2 -2
  73. data/lib/aspera/preview/generator.rb +5 -5
  74. data/lib/aspera/preview/terminal.rb +3 -2
  75. data/lib/aspera/preview/utils.rb +3 -3
  76. data/lib/aspera/proxy_auto_config.rb +4 -4
  77. data/lib/aspera/rest.rb +175 -144
  78. data/lib/aspera/rest_errors_aspera.rb +3 -3
  79. data/lib/aspera/resumer.rb +77 -0
  80. data/lib/aspera/ssh.rb +6 -1
  81. data/lib/aspera/{fasp → transfer}/error.rb +3 -3
  82. data/lib/aspera/{fasp → transfer}/error_info.rb +1 -1
  83. data/lib/aspera/{fasp → transfer}/faux_file.rb +1 -1
  84. data/lib/aspera/{fasp → transfer}/parameters.rb +58 -89
  85. data/lib/aspera/{fasp/transfer_spec.rb → transfer/spec.rb} +18 -16
  86. data/lib/aspera/{fasp/parameters.yaml → transfer/spec.yaml} +4 -99
  87. data/lib/aspera/{fasp → transfer}/sync.rb +32 -32
  88. data/lib/aspera/{fasp → transfer}/uri.rb +9 -8
  89. data/lib/aspera/web_server_simple.rb +11 -3
  90. data.tar.gz.sig +0 -0
  91. metadata +36 -63
  92. metadata.gz.sig +0 -0
  93. data/lib/aspera/aoc.rb +0 -601
  94. data/lib/aspera/ats_api.rb +0 -47
  95. data/lib/aspera/cos_node.rb +0 -94
  96. data/lib/aspera/fasp/resume_policy.rb +0 -79
  97. data/lib/aspera/node.rb +0 -339
@@ -7,9 +7,9 @@ require 'aspera/preview/options'
7
7
  require 'aspera/preview/utils'
8
8
  require 'aspera/preview/file_types'
9
9
  require 'aspera/preview/terminal'
10
- require 'aspera/fasp/transfer_spec'
10
+ require 'aspera/transfer/spec'
11
11
  require 'aspera/persistency_action_once'
12
- require 'aspera/node'
12
+ require 'aspera/api/node'
13
13
  require 'aspera/hash_ext'
14
14
  require 'aspera/timer_limiter'
15
15
  require 'aspera/id_generator'
@@ -20,7 +20,7 @@ require 'securerandom'
20
20
  module Aspera
21
21
  module Cli
22
22
  module Plugins
23
- class Preview < Aspera::Cli::BasicAuthPlugin
23
+ class Preview < Cli::BasicAuthPlugin
24
24
  # special tag to identify transfers related to generator
25
25
  PREV_GEN_TAG = 'preview_generator'
26
26
  # defined by node API: suffix for folder containing previews
@@ -49,8 +49,8 @@ module Aspera
49
49
  attr_accessor :option_previews_folder
50
50
  attr_accessor :option_folder_reset_cache, :option_skip_folders, :option_overwrite, :option_file_access
51
51
 
52
- def initialize(env)
53
- super(env)
52
+ def initialize(**env)
53
+ super
54
54
  @skip_types = []
55
55
  @default_transfer_spec = nil
56
56
  # by default generate all supported formats (clone, as altered by options)
@@ -96,7 +96,7 @@ module Aspera
96
96
  end
97
97
 
98
98
  options.parse_options!
99
- assert_type(@option_skip_folders, Array){'skip_folder'}
99
+ Aspera.assert_type(@option_skip_folders, Array){'skip_folder'}
100
100
  @tmp_folder = File.join(options.get_option(:temp_folder, mandatory: true), "#{TMP_DIR_PREFIX}.#{SecureRandom.uuid}")
101
101
  FileUtils.mkdir_p(@tmp_folder)
102
102
  Log.log.debug{"tmpdir: #{@tmp_folder}"}
@@ -106,7 +106,7 @@ module Aspera
106
106
  @skip_types = []
107
107
  value.split(',').each do |v|
108
108
  s = v.to_sym
109
- assert_values(s, Aspera::Preview::FileTypes::CONVERSION_TYPES){'skip_types'}
109
+ Aspera.assert_values(s, Aspera::Preview::FileTypes::CONVERSION_TYPES){'skip_types'}
110
110
  @skip_types.push(s)
111
111
  end
112
112
  end
@@ -128,7 +128,7 @@ 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(operation: 'GET', subpath: "files/#{file_id}/files", headers: headers, url_params: request_args)[:data]
132
132
  # return @api_node.read("files/#{file_id}/files",request_args)[:data]
133
133
  end
134
134
 
@@ -153,11 +153,11 @@ module Aspera
153
153
  end
154
154
  return if events.empty?
155
155
  events.each do |event|
156
- if event['data']['direction'].eql?(Fasp::TransferSpec::DIRECTION_RECEIVE) &&
156
+ if event['data']['direction'].eql?(Transfer::Spec::DIRECTION_RECEIVE) &&
157
157
  event['data']['status'].eql?('completed') &&
158
158
  event['data']['error_code'].eql?(0) &&
159
- event['data'].dig('tags', Fasp::TransferSpec::TAG_RESERVED, PREV_GEN_TAG).nil?
160
- folder_id = event.dig('data', 'tags', Fasp::TransferSpec::TAG_RESERVED, 'node', 'file_id')
159
+ event['data'].dig('tags', Transfer::Spec::TAG_RESERVED, PREV_GEN_TAG).nil?
160
+ folder_id = event.dig('data', 'tags', Transfer::Spec::TAG_RESERVED, 'node', 'file_id')
161
161
  folder_id ||= event.dig('data', 'file_id')
162
162
  if !folder_id.nil?
163
163
  folder_entry = @api_node.read("files/#{folder_id}")[:data] rescue nil
@@ -191,7 +191,7 @@ module Aspera
191
191
  if event.dig('data', 'type').eql?('file')
192
192
  file_entry = @api_node.read("files/#{event['data']['id']}")[:data] rescue nil
193
193
  if !file_entry.nil? &&
194
- @option_skip_folders.select{|d|file_entry['path'].start_with?(d)}.empty?
194
+ @option_skip_folders.none?{|d|file_entry['path'].start_with?(d)}
195
195
  file_entry['parent_file_id'] = event['data']['parent_file_id']
196
196
  if event['types'].include?('file.deleted')
197
197
  Log.log.error('TODO'.red)
@@ -213,10 +213,10 @@ module Aspera
213
213
  end
214
214
 
215
215
  def do_transfer(direction, folder_id, source_filename, destination='/')
216
- assert(!(destination.nil? && direction.eql?(Fasp::TransferSpec::DIRECTION_RECEIVE)))
216
+ Aspera.assert(!(destination.nil? && direction.eql?(Transfer::Spec::DIRECTION_RECEIVE)))
217
217
  t_spec = @api_node.transfer_spec_gen4(folder_id, direction, {
218
218
  'paths' => [{'source' => source_filename}],
219
- 'tags' => {Fasp::TransferSpec::TAG_RESERVED => {PREV_GEN_TAG => true}}
219
+ 'tags' => {Transfer::Spec::TAG_RESERVED => {PREV_GEN_TAG => true}}
220
220
  })
221
221
  # force destination, need to set this in transfer agent else it gets overwritten, not do: t_spec['destination_root']=destination
222
222
  transfer.option_transfer_spec_deep_merge({'destination_root' => destination})
@@ -318,7 +318,7 @@ module Aspera
318
318
  if @access_remote
319
319
  raise 'missing parent_file_id in entry' if entry['parent_file_id'].nil?
320
320
  # download original file to temp folder
321
- do_transfer(Fasp::TransferSpec::DIRECTION_RECEIVE, entry['parent_file_id'], entry['name'], @tmp_folder)
321
+ do_transfer(Transfer::Spec::DIRECTION_RECEIVE, entry['parent_file_id'], entry['name'], @tmp_folder)
322
322
  end
323
323
  Log.log.info{"source: #{entry['id']}: #{entry['path']}"}
324
324
  gen_infos.each do |gen_info|
@@ -326,7 +326,7 @@ module Aspera
326
326
  end
327
327
  if @access_remote
328
328
  # upload
329
- do_transfer(Fasp::TransferSpec::DIRECTION_SEND, @previews_folder_entry['id'], local_entry_preview_dir)
329
+ do_transfer(Transfer::Spec::DIRECTION_SEND, @previews_folder_entry['id'], local_entry_preview_dir)
330
330
  # cleanup after upload
331
331
  FileUtils.rm_rf(local_entry_preview_dir)
332
332
  File.delete(File.join(@tmp_folder, entry['name']))
@@ -403,8 +403,8 @@ module Aspera
403
403
  command = options.get_next_command(ACTIONS)
404
404
  unless %i[check test show].include?(command)
405
405
  # this will use node api
406
- @api_node = Aspera::Node.new(params: basic_auth_params)
407
- @transfer_server_address = URI.parse(@api_node.params[:base_url]).host
406
+ @api_node = Api::Node.new(**basic_auth_params)
407
+ @transfer_server_address = URI.parse(@api_node.base_url).host
408
408
  # get current access key
409
409
  @access_key_self = @api_node.read('access_keys/self')[:data]
410
410
  # TODO: check events is activated here:
@@ -422,13 +422,13 @@ module Aspera
422
422
  raise Cli::Error, "Folder #{@option_previews_folder} does not exist on node. " \
423
423
  'Please create it in the storage root, or specify an alternate name.' if @previews_folder_entry.nil?
424
424
  else
425
- assert(@access_key_self['storage']['type'].eql?('local')){'only local storage allowed in this mode'}
425
+ Aspera.assert(@access_key_self['storage']['type'].eql?('local')){'only local storage allowed in this mode'}
426
426
  @local_storage_root = @access_key_self['storage']['path']
427
427
  # TODO: option to override @local_storage_root='xxx'
428
428
  @local_storage_root = @local_storage_root[PVCL_LOCAL_STORAGE.length..-1] if @local_storage_root.start_with?(PVCL_LOCAL_STORAGE)
429
429
  # TODO: windows could have "C:" ?
430
- assert(@local_storage_root.start_with?('/')){"not local storage: #{@local_storage_root}"}
431
- assert(File.directory?(@local_storage_root), exception_class: Cli::Error){"Local storage root folder #{@local_storage_root} does not exist."}
430
+ Aspera.assert(@local_storage_root.start_with?('/')){"not local storage: #{@local_storage_root}"}
431
+ Aspera.assert(File.directory?(@local_storage_root), exception_class: Cli::Error){"Local storage root folder #{@local_storage_root} does not exist."}
432
432
  @local_preview_folder = File.join(@local_storage_root, @option_previews_folder)
433
433
  raise Cli::Error, "Folder #{@local_preview_folder} does not exist locally. " \
434
434
  'Please create it, or specify an alternate name.' unless File.directory?(@local_preview_folder)
@@ -437,7 +437,7 @@ module Aspera
437
437
  Log.log.debug{"marker file: #{marker_file}"}
438
438
  if File.exist?(marker_file)
439
439
  ak = File.read(marker_file).chomp
440
- assert(@access_key_self['id'].eql?(ak)){"mismatch access key in #{marker_file}: contains #{ak}, using #{@access_key_self['id']}"}
440
+ Aspera.assert(@access_key_self['id'].eql?(ak)){"mismatch access key in #{marker_file}: contains #{ak}, using #{@access_key_self['id']}"}
441
441
  else
442
442
  File.write(marker_file, @access_key_self['id'])
443
443
  end
@@ -461,15 +461,15 @@ module Aspera
461
461
  else
462
462
  @api_node.read("files/#{scan_id}")[:data]
463
463
  end
464
- @filter_block = Aspera::Node.file_matcher_from_argument(options)
464
+ @filter_block = Api::Node.file_matcher_from_argument(options)
465
465
  scan_folder_files(folder_info, scan_path)
466
466
  return Main.result_status('scan finished')
467
467
  when :events, :trevents
468
- @filter_block = Aspera::Node.file_matcher_from_argument(options)
468
+ @filter_block = Api::Node.file_matcher_from_argument(options)
469
469
  iteration_persistency = nil
470
470
  if options.get_option(:once_only, mandatory: true)
471
471
  iteration_persistency = PersistencyActionOnce.new(
472
- manager: @agents[:persistency],
472
+ manager: persistency,
473
473
  data: [],
474
474
  id: IdGenerator.from_list([
475
475
  'preview_iteration',
@@ -479,7 +479,7 @@ module Aspera
479
479
  ]))
480
480
  end
481
481
  # call processing method specified by command line command
482
- send("process_#{command}", iteration_persistency)
482
+ send(:"process_#{command}", iteration_persistency)
483
483
  return Main.result_status("#{command} finished")
484
484
  when :check
485
485
  return Main.result_status('Tools validated')
@@ -501,8 +501,8 @@ module Aspera
501
501
  ensure
502
502
  Log.log.debug{"cleaning up temp folder #{@tmp_folder}"}
503
503
  FileUtils.rm_rf(@tmp_folder)
504
- end # execute_action
505
- end # Preview
506
- end # Plugins
507
- end # Cli
508
- end # Aspera
504
+ end
505
+ end
506
+ end
507
+ end
508
+ end
@@ -3,7 +3,7 @@
3
3
  # cspell:ignore ascmd zmode zuid zgid fasping
4
4
  require 'aspera/cli/basic_auth_plugin'
5
5
  require 'aspera/cli/sync_actions'
6
- require 'aspera/fasp/transfer_spec'
6
+ require 'aspera/transfer/spec'
7
7
  require 'aspera/ascmd'
8
8
  require 'aspera/ssh'
9
9
  require 'aspera/nagios'
@@ -16,7 +16,7 @@ module Aspera
16
16
  module Cli
17
17
  module Plugins
18
18
  # implement basic remote access with FASP/SSH
19
- class Server < Aspera::Cli::BasicAuthPlugin
19
+ class Server < Cli::BasicAuthPlugin
20
20
  include SyncActions
21
21
  SSH_SCHEME = 'ssh'
22
22
  LOCAL_SCHEME = 'local'
@@ -53,27 +53,27 @@ module Aspera
53
53
  [address_or_url]
54
54
  else
55
55
  [
56
- "ssh://#{address_or_url}:33001",
57
- "ssh://#{address_or_url}:22"
56
+ "#{SSH_SCHEME}://#{address_or_url}:33001",
57
+ "#{SSH_SCHEME}://#{address_or_url}:22"
58
58
  ]
59
59
  # wss not practical as it requires a token
60
60
  end
61
-
61
+ error = nil
62
62
  urls.each do |base_url|
63
63
  server_uri = URI.parse(base_url)
64
64
  Log.log.debug{"URI=#{server_uri}, host=#{server_uri.hostname}, port=#{server_uri.port}, scheme=#{server_uri.scheme}"}
65
65
  next unless server_uri.scheme.eql?(SSH_SCHEME)
66
- begin
67
- socket = TCPSocket.new(server_uri.hostname, server_uri.port)
68
- socket.puts('SSH-2.0-Ascli_0.0')
69
- version = socket.gets.chomp
70
- if version.match?(/^SSH-2.0-/)
71
- return {version: version.gsub(/^SSH-2.0-/, ''), url: base_url}
72
- end
73
- rescue StandardError => e
74
- Log.log.debug{"detect error: #{e}"}
66
+ socket = TCPSocket.new(server_uri.hostname, server_uri.port)
67
+ socket.puts('SSH-2.0-Ascli_0.0')
68
+ version = socket.gets.chomp
69
+ if version.match?(/^SSH-2.0-/)
70
+ return {version: version.gsub(/^SSH-2.0-/, ''), url: base_url}
75
71
  end
72
+ rescue StandardError => e
73
+ error = e
74
+ Log.log.debug{"detect error: #{e}"}
76
75
  end
76
+ raise error if error
77
77
  return nil
78
78
  end
79
79
 
@@ -90,8 +90,8 @@ module Aspera
90
90
  end
91
91
  end
92
92
 
93
- def initialize(env)
94
- super(env)
93
+ def initialize(**env)
94
+ super
95
95
  options.declare(:ssh_keys, 'SSH key path list (Array or single)')
96
96
  options.declare(:passphrase, 'SSH private key passphrase')
97
97
  options.declare(:ssh_options, 'SSH options', types: Hash, default: {})
@@ -127,14 +127,14 @@ module Aspera
127
127
  if !server_uri.scheme.eql?(SSH_SCHEME)
128
128
  Log.log.warn('URL scheme is https but no token was provided in transfer spec.')
129
129
  Log.log.warn("If you want to access the server, not using WSS for session, then use a URL with scheme \"#{SSH_SCHEME}\" and proper SSH port")
130
- assumed_url = "#{SSH_SCHEME}://#{server_transfer_spec['remote_host']}:#{Aspera::Fasp::TransferSpec::SSH_PORT}"
130
+ assumed_url = "#{SSH_SCHEME}://#{server_transfer_spec['remote_host']}:#{Transfer::Spec::SSH_PORT}"
131
131
  Log.log.warn{"Assuming proper URL is: #{assumed_url}"}
132
132
  server_uri = URI.parse(assumed_url)
133
133
  end
134
134
  # Scheme is SSH
135
135
  if options.get_option(:username).nil?
136
- options.set_option(:username, Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER)
137
- Log.log.info{"No username provided: Assuming default transfer user: #{Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER}"}
136
+ options.set_option(:username, Transfer::Spec::ACCESS_KEY_TRANSFER_USER)
137
+ Log.log.info{"No username provided: Assuming default transfer user: #{Transfer::Spec::ACCESS_KEY_TRANSFER_USER}"}
138
138
  end
139
139
  server_transfer_spec['remote_user'] = options.get_option(:username, mandatory: true)
140
140
  if !server_uri.port.nil?
@@ -151,16 +151,14 @@ module Aspera
151
151
  ssh_key_list = options.get_option(:ssh_keys)
152
152
  if !ssh_key_list.nil?
153
153
  ssh_key_list = [ssh_key_list] if ssh_key_list.is_a?(String)
154
- assert_type(ssh_key_list, Array){'ssh_keys'}
155
- assert(ssh_key_list.all?(String))
154
+ Aspera.assert_type(ssh_key_list, Array){'ssh_keys'}
155
+ Aspera.assert(ssh_key_list.all?(String))
156
156
  ssh_key_list.map!{|p|File.expand_path(p)}
157
157
  Log.log.debug{"SSH keys=#{ssh_key_list}"}
158
158
  if !ssh_key_list.empty?
159
159
  @ssh_opts[:keys] = ssh_key_list
160
- server_transfer_spec['EX_ssh_key_paths'] = ssh_key_list
161
- ssh_key_list.each do |k|
162
- Log.log.warn{"No such key file: #{k}"} unless File.exist?(k)
163
- end
160
+ server_transfer_spec['ssh_private_key'] = File.read(ssh_key_list.first)
161
+ Log.log.warn{'Using only first SSH key for transfers'} unless ssh_key_list.length.eql?(1)
164
162
  cred_set = true
165
163
  end
166
164
  end
@@ -178,7 +176,7 @@ module Aspera
178
176
  def execute_transfer(command, transfer_spec)
179
177
  case command
180
178
  when :upload, :download
181
- Fasp::TransferSpec.action_to_direction(transfer_spec, command)
179
+ Transfer::Spec.action_to_direction(transfer_spec, command)
182
180
  return Main.result_transfer(transfer.start(transfer_spec))
183
181
  when :sync
184
182
  # lets ignore the arguments provided by execute_sync_action, we just give the transfer spec
@@ -189,7 +187,7 @@ module Aspera
189
187
  # actions without ascmd
190
188
  BASE_ACTIONS = %i[health].concat(TRANSFER_COMMANDS).freeze
191
189
  # all actions
192
- ACTIONS = [BASE_ACTIONS, Aspera::AsCmd::OPERATIONS, ASCMD_ALIASES.keys].flatten.freeze
190
+ ACTIONS = [BASE_ACTIONS, AsCmd::OPERATIONS, ASCMD_ALIASES.keys].flatten.freeze
193
191
 
194
192
  def execute_action
195
193
  server_transfer_spec = options_to_base_transfer_spec
@@ -228,16 +226,16 @@ module Aspera
228
226
  else
229
227
  nagios.add_critical('transfer', statuses.reject{|i|i.eql?(:success)}.first.to_s)
230
228
  end
231
- else error_unexpected_value(command_nagios)
229
+ else Aspera.error_unexpected_value(command_nagios)
232
230
  end
233
231
  return nagios.result
234
232
  when *TRANSFER_COMMANDS
235
233
  return execute_transfer(command, server_transfer_spec)
236
- when *Aspera::AsCmd::OPERATIONS
234
+ when *AsCmd::OPERATIONS
237
235
  command_arguments = options.get_next_argument('ascmd command arguments', expected: :multiple, mandatory: false)
238
- ascmd = Aspera::AsCmd.new(ascmd_executor)
236
+ ascmd = AsCmd.new(ascmd_executor)
239
237
  begin
240
- result = ascmd.send(:execute_single, command, command_arguments)
238
+ result = ascmd.execute_single(command, command_arguments)
241
239
  case command
242
240
  when :mkdir, :mv, :cp, :rm
243
241
  return Main.result_success
@@ -248,10 +246,10 @@ module Aspera
248
246
  when :du, :md5sum, :info
249
247
  return {type: :single_object, data: result.stringify_keys}
250
248
  end
251
- rescue Aspera::AsCmd::Error => e
249
+ rescue AsCmd::Error => e
252
250
  raise Cli::BadArgument, e.extended_message
253
251
  end
254
- else error_unreachable_line
252
+ else Aspera.error_unreachable_line
255
253
  end
256
254
  end # execute_action
257
255
  end # Server
@@ -6,7 +6,7 @@ module Aspera
6
6
  module Cli
7
7
  module Plugins
8
8
  # Plugin for Aspera Shares v1
9
- class Shares < Aspera::Cli::BasicAuthPlugin
9
+ class Shares < Cli::BasicAuthPlugin
10
10
  API_BASE = 'node_api'
11
11
  class << self
12
12
  def detect(address_or_url)
@@ -24,7 +24,7 @@ module Aspera
24
24
  end
25
25
  return nil unless found
26
26
  version = 'unknown'
27
- test_page = api.call({ operation: 'GET', subpath: 'login' })
27
+ test_page = api.call(operation: 'GET', subpath: 'login')
28
28
  if (m = test_page[:http].body.match(/\(v(1\..*)\)/))
29
29
  version = m[1]
30
30
  end
@@ -47,8 +47,8 @@ module Aspera
47
47
  end
48
48
  end
49
49
 
50
- def initialize(env)
51
- super(env)
50
+ def initialize(**env)
51
+ super
52
52
  end
53
53
 
54
54
  SAML_IMPORT_MANDATORY = %w[id name_id].freeze
@@ -79,7 +79,7 @@ module Aspera
79
79
  when :repository, :files
80
80
  api_shares_node = basic_auth_api(API_BASE)
81
81
  repo_command = options.get_next_command(Node::COMMANDS_SHARES)
82
- return Node.new(@agents, api: api_shares_node).execute_action(repo_command)
82
+ return Node.new(**init_params, api: api_shares_node).execute_action(repo_command)
83
83
  when :admin
84
84
  api_shares_admin = basic_auth_api('api/v1')
85
85
  admin_command = options.get_next_command(%i[node share transfer_settings user group].freeze)
@@ -102,17 +102,19 @@ module Aspera
102
102
  when :user, :group
103
103
  entity_type = admin_command
104
104
  entities_location = options.get_next_command(%i[all local ldap saml])
105
- entities_path = "data/#{entities_location}_#{entity_type}s"
105
+ entities_prefix = entities_location.eql?(:all) ? '' : "#{entities_location}_"
106
+ entities_path = "data/#{entities_prefix}#{entity_type}s"
106
107
  entity_action = nil
107
108
  case entities_location
108
109
  when :all
109
- entities_path = "data/#{entity_type}s"
110
110
  entity_action = %i[list show delete]
111
111
  entity_action.concat(USR_GRP_SETTINGS)
112
112
  entity_action.push(:users) if entity_type.eql?(:group)
113
113
  entity_action.freeze
114
114
  when :local
115
- entity_action = %i[list show delete create modify].freeze
115
+ entity_action = %i[list show delete create modify]
116
+ entity_action.push(:users) if entity_type.eql?(:group)
117
+ entity_action.freeze
116
118
  when :ldap
117
119
  entity_action = %i[add].freeze
118
120
  when :saml
@@ -131,7 +133,7 @@ module Aspera
131
133
  when :import # saml
132
134
  return do_bulk_operation(command: entity_verb, descr: 'user information') do |entity_parameters|
133
135
  entity_parameters = entity_parameters.transform_keys{|k|k.gsub(/\s+/, '_').downcase}
134
- assert_type(entity_parameters, Hash)
136
+ Aspera.assert_type(entity_parameters, Hash)
135
137
  SAML_IMPORT_MANDATORY.each{|p|raise "missing mandatory field: #{p}" if entity_parameters[p].nil?}
136
138
  entity_parameters.each_key do |p|
137
139
  raise "unsupported field: #{p}, use: #{SAML_IMPORT_ALLOWED.join(',')}" unless SAML_IMPORT_ALLOWED.include?(p)
@@ -143,8 +145,8 @@ module Aspera
143
145
  api_shares_admin.create(entities_path, {entity_type=>entity_name})[:data]
144
146
  end
145
147
  when :users # group
146
- raise "TODO, not implemented"
147
- else error_unexpected_value(entity_verb)
148
+ return entity_action(api_shares_admin, "#{entities_path}/#{instance_identifier}/#{entities_prefix}users")
149
+ else Aspera.error_unexpected_value(entity_verb)
148
150
  end
149
151
  end
150
152
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'aspera/fasp/sync'
3
+ require 'aspera/transfer/sync'
4
4
  require 'aspera/assert'
5
5
 
6
6
  module Aspera
@@ -8,7 +8,7 @@ module Aspera
8
8
  # Module for sync actions
9
9
  module SyncActions
10
10
  SIMPLE_ARGUMENTS_SYNC = {
11
- direction: Aspera::Fasp::Sync::DIRECTIONS,
11
+ direction: Transfer::Sync::DIRECTIONS,
12
12
  local_dir: String,
13
13
  remote_dir: String
14
14
  }.stringify_keys.freeze
@@ -20,7 +20,7 @@ module Aspera
20
20
  end
21
21
 
22
22
  def execute_sync_action(&block)
23
- assert(block){'No block given'}
23
+ Aspera.assert(block){'No block given'}
24
24
  command = options.get_next_command(%i[start admin])
25
25
  # try to get 3 arguments as simple arguments
26
26
  case command
@@ -45,13 +45,13 @@ module Aspera
45
45
  :sync_info,
46
46
  mandatory: false,
47
47
  default: {'sessions' => [{'name' => File.basename(simple_session_args['local_dir'])}]})
48
- assert_type(async_params, Hash){'sync_info'}
49
- assert_type(async_params['sessions'], Array){'sync_info[sessions]'}
50
- assert_type(async_params['sessions'].first, Hash){'sync_info[sessions][0]'}
48
+ Aspera.assert_type(async_params, Hash){'sync_info'}
49
+ Aspera.assert_type(async_params['sessions'], Array){'sync_info[sessions]'}
50
+ Aspera.assert_type(async_params['sessions'].first, Hash){'sync_info[sessions][0]'}
51
51
  async_params['sessions'].first.merge!(simple_session_args)
52
52
  end
53
53
  Log.log.debug{Log.dump('async_params', async_params)}
54
- Aspera::Fasp::Sync.start(async_params, &block)
54
+ Transfer::Sync.start(async_params, &block)
55
55
  return Main.result_success
56
56
  when :admin
57
57
  command2 = options.get_next_command([:status])
@@ -59,7 +59,7 @@ module Aspera
59
59
  when :status
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
- return {type: :single_object, data: Aspera::Fasp::Sync.admin_status(async_params, sync_session_name)}
62
+ return {type: :single_object, data: Transfer::Sync.admin_status(async_params, sync_session_name)}
63
63
  end # command2
64
64
  end # command
65
65
  end # execute_action
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'aspera/fasp/agent_base'
4
- require 'aspera/fasp/transfer_spec'
3
+ require 'aspera/agent/base'
4
+ require 'aspera/transfer/spec'
5
5
  require 'aspera/cli/info'
6
6
  require 'aspera/log'
7
7
  require 'aspera/assert'
@@ -31,7 +31,7 @@ module Aspera
31
31
  :FILE_LIST_FROM_TRANSFER_SPEC,
32
32
  :FILE_LIST_OPTIONS,
33
33
  :DEFAULT_TRANSFER_NOTIFY_TEMPLATE
34
- TRANSFER_AGENTS = Fasp::AgentBase.agent_list.freeze
34
+ TRANSFER_AGENTS = Agent::Base.agent_list.freeze
35
35
 
36
36
  class << self
37
37
  # @return :success if all sessions statuses returned by "start" are success
@@ -55,6 +55,8 @@ module Aspera
55
55
  @agent = nil
56
56
  # source/destination pair, like "paths" of transfer spec
57
57
  @transfer_paths = nil
58
+ # HTTPGW URL provided by webapp
59
+ @httpgw_url_lambda = nil
58
60
  @opt_mgr.declare(:ts, 'Override transfer spec values', types: Hash, handler: {o: self, m: :option_transfer_spec})
59
61
  @opt_mgr.declare(:to_folder, 'Destination folder for transferred files')
60
62
  @opt_mgr.declare(:sources, "How list of transferred files is provided (#{FILE_LIST_OPTIONS.join(',')})")
@@ -68,7 +70,7 @@ module Aspera
68
70
 
69
71
  # multiple option are merged
70
72
  def option_transfer_spec=(value)
71
- assert_type(value, Hash){'ts'}
73
+ Aspera.assert_type(value, Hash){'ts'}
72
74
  @transfer_spec_command_line.deep_merge!(value)
73
75
  end
74
76
 
@@ -95,11 +97,12 @@ module Aspera
95
97
  end
96
98
 
97
99
  # analyze options and create new agent if not already created or set
100
+ # TODO: make a Factory pattern
98
101
  def agent_instance
99
102
  return @agent unless @agent.nil?
100
103
  agent_type = @opt_mgr.get_option(:transfer, mandatory: true)
101
104
  # agent plugin is loaded on demand to avoid loading unnecessary dependencies
102
- require "aspera/fasp/agent_#{agent_type}"
105
+ require "aspera/agent/#{agent_type}"
103
106
  # set keys as symbols
104
107
  agent_options = @opt_mgr.get_option(:transfer_info).symbolize_keys
105
108
  # special cases
@@ -113,12 +116,17 @@ module Aspera
113
116
  when :direct
114
117
  # by default do not display ascp native progress bar
115
118
  agent_options[:quiet] = true unless agent_options.key?(:quiet)
116
- agent_options[:check_ignore] = ->(host, port){@config.ignore_cert?(host, port)}
117
- agent_options[:trusted_certs] = @config.trusted_cert_locations(files_only: true) unless agent_options.key?(:trusted_certs)
119
+ agent_options[:check_ignore_cb] = ->(host, port){@config.ignore_cert?(host, port)}
120
+ agent_options[:trusted_certs] = @config.trusted_cert_locations unless agent_options.key?(:trusted_certs)
121
+ when :httpgw
122
+ unless agent_options.key?(:url) || @httpgw_url_lambda.nil?
123
+ Log.log.debug('retrieving HTTPGW URL from webapp')
124
+ agent_options[:url] = @httpgw_url_lambda.call
125
+ end
118
126
  end
119
127
  agent_options[:progress] = @config.progress_bar
120
128
  # get agent instance
121
- new_agent = Kernel.const_get("Aspera::Fasp::Agent#{agent_type.capitalize}").new(agent_options)
129
+ new_agent = Kernel.const_get("Aspera::Agent::#{agent_type.capitalize}").new(agent_options)
122
130
  self.agent_instance = new_agent
123
131
  Log.log.debug{"transfer agent is a #{@agent.class}"}
124
132
  return @agent
@@ -135,9 +143,9 @@ module Aspera
135
143
  return dest_folder unless dest_folder.nil?
136
144
  # default: / on remote, . on local
137
145
  case direction.to_s
138
- when Fasp::TransferSpec::DIRECTION_SEND then dest_folder = '/'
139
- when Fasp::TransferSpec::DIRECTION_RECEIVE then dest_folder = '.'
140
- else error_unexpected_value(direction)
146
+ when Transfer::Spec::DIRECTION_SEND then dest_folder = '/'
147
+ when Transfer::Spec::DIRECTION_RECEIVE then dest_folder = '.'
148
+ else Aspera.error_unexpected_value(direction)
141
149
  end
142
150
  return dest_folder
143
151
  end
@@ -149,6 +157,11 @@ module Aspera
149
157
  end
150
158
  end
151
159
 
160
+ def httpgw_url_cb=(httpgw_url_proc)
161
+ Aspera.assert_type(httpgw_url_proc, Proc){'httpgw_url_cb'}
162
+ @httpgw_url_lambda = httpgw_url_proc
163
+ end
164
+
152
165
  # This is how the list of files to be transferred is specified
153
166
  # get paths suitable for transfer spec from command line
154
167
  # @return [Hash] {source: (mandatory), destination: (optional)}
@@ -171,7 +184,7 @@ module Aspera
171
184
  Log.log.debug('assume list provided in transfer spec')
172
185
  special_case_direct_with_list =
173
186
  @opt_mgr.get_option(:transfer, mandatory: true).eql?(:direct) &&
174
- Fasp::Parameters.ts_has_ascp_file_list(@transfer_spec_command_line, @opt_mgr.get_option(:transfer_info))
187
+ Transfer::Parameters.ascp_args_file_list?(@opt_mgr.get_option(:transfer_info)['ascp_args'])
175
188
  raise Cli::BadArgument, 'transfer spec on command line must have sources' if @transfer_paths.nil? && !special_case_direct_with_list
176
189
  # here we assume check of sources is made in transfer agent
177
190
  return @transfer_paths
@@ -185,15 +198,15 @@ module Aspera
185
198
  if !@transfer_paths.nil?
186
199
  Log.log.warn('--sources overrides paths from --ts')
187
200
  end
188
- source_type=@opt_mgr.get_option(:src_type, mandatory: true)
201
+ source_type = @opt_mgr.get_option(:src_type, mandatory: true)
189
202
  case source_type
190
203
  when :list
191
204
  # when providing a list, just specify source
192
205
  @transfer_paths = file_list.map{|i|{'source' => i}}
193
206
  when :pair
194
- assert(file_list.length.even?, exception_class: Cli::BadArgument){"When using pair, provide an even number of paths: #{file_list.length}"}
207
+ Aspera.assert(file_list.length.even?, exception_class: Cli::BadArgument){"When using pair, provide an even number of paths: #{file_list.length}"}
195
208
  @transfer_paths = file_list.each_slice(2).to_a.map{|s, d|{'source' => s, 'destination' => d}}
196
- else error_unexpected_value(source_type)
209
+ else Aspera.error_unexpected_value(source_type)
197
210
  end
198
211
  Log.log.debug{"paths=#{@transfer_paths}"}
199
212
  return @transfer_paths
@@ -204,14 +217,14 @@ module Aspera
204
217
  # @param rest_token [Rest] if oauth token regeneration supported
205
218
  def start(transfer_spec, rest_token: nil)
206
219
  # check parameters
207
- assert_type(transfer_spec, Hash){'transfer_spec'}
220
+ Aspera.assert_type(transfer_spec, Hash){'transfer_spec'}
208
221
  # process :src option
209
222
  case transfer_spec['direction']
210
- when Fasp::TransferSpec::DIRECTION_RECEIVE
223
+ when Transfer::Spec::DIRECTION_RECEIVE
211
224
  # init default if required in any case
212
225
  @transfer_spec_command_line['destination_root'] ||= destination_folder(transfer_spec['direction'])
213
- when Fasp::TransferSpec::DIRECTION_SEND
214
- if transfer_spec.dig('tags', Fasp::TransferSpec::TAG_RESERVED, 'node', 'access_key')
226
+ when Transfer::Spec::DIRECTION_SEND
227
+ if transfer_spec.dig('tags', Transfer::Spec::TAG_RESERVED, 'node', 'access_key')
215
228
  # gen4
216
229
  @transfer_spec_command_line.delete('destination_root') if @transfer_spec_command_line.key?('destination_root_id')
217
230
  elsif transfer_spec.key?('token')
@@ -26,7 +26,7 @@ module Aspera
26
26
 
27
27
  def event(session_id:, type:, info: nil)
28
28
  Log.log.debug{"progress: #{type} #{session_id} #{info}"}
29
- assert(!session_id.nil? || type.eql?(:pre_start)){'session_id is nil'}
29
+ Aspera.assert(!session_id.nil? || type.eql?(:pre_start)){'session_id is nil'}
30
30
  return if @completed
31
31
  if @progress_bar.nil?
32
32
  @progress_bar = ProgressBar.create(
@@ -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.16.0'
7
+ VERSION = '4.17.0'
8
8
  end
9
9
  end
data/lib/aspera/colors.rb CHANGED
@@ -53,4 +53,9 @@ class String
53
53
  define_method(name){self}
54
54
  end
55
55
  end
56
+ def capital_to_snake
57
+ return gsub(/([a-z\d])([A-Z])/, '\1_\2')
58
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
59
+ .downcase
60
+ end
56
61
  end