aspera-cli 4.15.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 (108) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/BUGS.md +29 -3
  4. data/CHANGELOG.md +375 -280
  5. data/CONTRIBUTING.md +71 -18
  6. data/README.md +1978 -1656
  7. data/bin/ascli +13 -31
  8. data/bin/asession +32 -22
  9. data/examples/dascli +2 -2
  10. data/lib/aspera/agent/alpha.rb +117 -0
  11. data/lib/aspera/agent/base.rb +61 -0
  12. data/lib/aspera/{fasp/agent_connect.rb → agent/connect.rb} +13 -11
  13. data/lib/aspera/{fasp/agent_direct.rb → agent/direct.rb} +116 -116
  14. data/lib/aspera/{fasp/agent_httpgw.rb → agent/httpgw.rb} +21 -19
  15. data/lib/aspera/{fasp/agent_node.rb → agent/node.rb} +21 -33
  16. data/lib/aspera/agent/trsdk.rb +188 -0
  17. data/lib/aspera/api/aoc.rb +586 -0
  18. data/lib/aspera/api/ats.rb +46 -0
  19. data/lib/aspera/api/cos_node.rb +95 -0
  20. data/lib/aspera/api/node.rb +344 -0
  21. data/lib/aspera/ascmd.rb +47 -14
  22. data/lib/aspera/{fasp → ascp}/installation.rb +54 -15
  23. data/lib/aspera/{fasp → ascp}/management.rb +14 -14
  24. data/lib/aspera/{fasp → ascp}/products.rb +1 -1
  25. data/lib/aspera/assert.rb +45 -0
  26. data/lib/aspera/cli/basic_auth_plugin.rb +11 -10
  27. data/lib/aspera/cli/extended_value.rb +5 -5
  28. data/lib/aspera/cli/formatter.rb +27 -14
  29. data/lib/aspera/cli/hints.rb +7 -6
  30. data/lib/aspera/cli/main.rb +49 -29
  31. data/lib/aspera/cli/manager.rb +46 -36
  32. data/lib/aspera/cli/plugin.rb +34 -20
  33. data/lib/aspera/cli/plugin_factory.rb +61 -0
  34. data/lib/aspera/cli/plugins/alee.rb +7 -7
  35. data/lib/aspera/cli/plugins/aoc.rb +168 -132
  36. data/lib/aspera/cli/plugins/ats.rb +33 -33
  37. data/lib/aspera/cli/plugins/bss.rb +3 -4
  38. data/lib/aspera/cli/plugins/config.rb +250 -272
  39. data/lib/aspera/cli/plugins/console.rb +8 -6
  40. data/lib/aspera/cli/plugins/cos.rb +20 -19
  41. data/lib/aspera/cli/plugins/faspex.rb +71 -60
  42. data/lib/aspera/cli/plugins/faspex5.rb +212 -133
  43. data/lib/aspera/cli/plugins/node.rb +83 -75
  44. data/lib/aspera/cli/plugins/orchestrator.rb +36 -44
  45. data/lib/aspera/cli/plugins/preview.rb +33 -31
  46. data/lib/aspera/cli/plugins/server.rb +33 -32
  47. data/lib/aspera/cli/plugins/shares.rb +39 -33
  48. data/lib/aspera/cli/sync_actions.rb +9 -9
  49. data/lib/aspera/cli/transfer_agent.rb +45 -25
  50. data/lib/aspera/cli/transfer_progress.rb +2 -3
  51. data/lib/aspera/cli/version.rb +1 -1
  52. data/lib/aspera/colors.rb +5 -0
  53. data/lib/aspera/command_line_builder.rb +16 -14
  54. data/lib/aspera/coverage.rb +21 -0
  55. data/lib/aspera/data_repository.rb +33 -2
  56. data/lib/aspera/environment.rb +5 -4
  57. data/lib/aspera/faspex_gw.rb +13 -11
  58. data/lib/aspera/faspex_postproc.rb +6 -5
  59. data/lib/aspera/id_generator.rb +4 -2
  60. data/lib/aspera/json_rpc.rb +10 -8
  61. data/lib/aspera/keychain/encrypted_hash.rb +46 -11
  62. data/lib/aspera/keychain/macos_security.rb +29 -22
  63. data/lib/aspera/log.rb +5 -4
  64. data/lib/aspera/nagios.rb +7 -2
  65. data/lib/aspera/node_simulator.rb +213 -0
  66. data/lib/aspera/oauth/base.rb +143 -0
  67. data/lib/aspera/oauth/factory.rb +124 -0
  68. data/lib/aspera/oauth/generic.rb +34 -0
  69. data/lib/aspera/oauth/jwt.rb +51 -0
  70. data/lib/aspera/oauth/url_json.rb +31 -0
  71. data/lib/aspera/oauth/web.rb +50 -0
  72. data/lib/aspera/oauth.rb +5 -328
  73. data/lib/aspera/open_application.rb +7 -7
  74. data/lib/aspera/persistency_action_once.rb +13 -14
  75. data/lib/aspera/persistency_folder.rb +3 -2
  76. data/lib/aspera/preview/file_types.rb +53 -267
  77. data/lib/aspera/preview/generator.rb +7 -5
  78. data/lib/aspera/preview/terminal.rb +17 -7
  79. data/lib/aspera/preview/utils.rb +8 -7
  80. data/lib/aspera/proxy_auto_config.rb +6 -3
  81. data/lib/aspera/rest.rb +187 -140
  82. data/lib/aspera/rest_error_analyzer.rb +1 -0
  83. data/lib/aspera/rest_errors_aspera.rb +5 -3
  84. data/lib/aspera/resumer.rb +77 -0
  85. data/lib/aspera/secret_hider.rb +5 -2
  86. data/lib/aspera/ssh.rb +15 -8
  87. data/lib/aspera/temp_file_manager.rb +1 -1
  88. data/lib/aspera/{fasp → transfer}/error.rb +3 -3
  89. data/lib/aspera/{fasp → transfer}/error_info.rb +1 -1
  90. data/lib/aspera/{fasp → transfer}/faux_file.rb +1 -1
  91. data/lib/aspera/{fasp → transfer}/parameters.rb +95 -120
  92. data/lib/aspera/{fasp/transfer_spec.rb → transfer/spec.rb} +23 -19
  93. data/lib/aspera/{fasp/parameters.yaml → transfer/spec.yaml} +4 -99
  94. data/lib/aspera/transfer/sync.rb +273 -0
  95. data/lib/aspera/{fasp → transfer}/uri.rb +10 -9
  96. data/lib/aspera/web_server_simple.rb +12 -3
  97. data.tar.gz.sig +0 -0
  98. metadata +92 -68
  99. metadata.gz.sig +0 -0
  100. data/lib/aspera/aoc.rb +0 -606
  101. data/lib/aspera/ats_api.rb +0 -47
  102. data/lib/aspera/cos_node.rb +0 -93
  103. data/lib/aspera/fasp/agent_aspera.rb +0 -126
  104. data/lib/aspera/fasp/agent_base.rb +0 -48
  105. data/lib/aspera/fasp/agent_trsdk.rb +0 -146
  106. data/lib/aspera/fasp/resume_policy.rb +0 -77
  107. data/lib/aspera/node.rb +0 -338
  108. data/lib/aspera/sync.rb +0 -219
@@ -7,18 +7,20 @@ 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'
16
+ require 'aspera/log'
17
+ require 'aspera/assert'
16
18
  require 'securerandom'
17
19
 
18
20
  module Aspera
19
21
  module Cli
20
22
  module Plugins
21
- class Preview < Aspera::Cli::BasicAuthPlugin
23
+ class Preview < Cli::BasicAuthPlugin
22
24
  # special tag to identify transfers related to generator
23
25
  PREV_GEN_TAG = 'preview_generator'
24
26
  # defined by node API: suffix for folder containing previews
@@ -47,8 +49,8 @@ module Aspera
47
49
  attr_accessor :option_previews_folder
48
50
  attr_accessor :option_folder_reset_cache, :option_skip_folders, :option_overwrite, :option_file_access
49
51
 
50
- def initialize(env)
51
- super(env)
52
+ def initialize(**env)
53
+ super
52
54
  @skip_types = []
53
55
  @default_transfer_spec = nil
54
56
  # by default generate all supported formats (clone, as altered by options)
@@ -94,7 +96,7 @@ module Aspera
94
96
  end
95
97
 
96
98
  options.parse_options!
97
- raise 'skip_folder shall be an Array, use @json:[...]' unless @option_skip_folders.is_a?(Array)
99
+ Aspera.assert_type(@option_skip_folders, Array){'skip_folder'}
98
100
  @tmp_folder = File.join(options.get_option(:temp_folder, mandatory: true), "#{TMP_DIR_PREFIX}.#{SecureRandom.uuid}")
99
101
  FileUtils.mkdir_p(@tmp_folder)
100
102
  Log.log.debug{"tmpdir: #{@tmp_folder}"}
@@ -104,7 +106,7 @@ module Aspera
104
106
  @skip_types = []
105
107
  value.split(',').each do |v|
106
108
  s = v.to_sym
107
- raise "not supported: #{v}" unless Aspera::Preview::FileTypes::CONVERSION_TYPES.include?(s)
109
+ Aspera.assert_values(s, Aspera::Preview::FileTypes::CONVERSION_TYPES){'skip_types'}
108
110
  @skip_types.push(s)
109
111
  end
110
112
  end
@@ -126,7 +128,7 @@ module Aspera
126
128
  def get_folder_entries(file_id, request_args=nil)
127
129
  headers = {'Accept' => 'application/json'}
128
130
  headers['X-Aspera-Cache-Control'] = 'no-cache' if @option_folder_reset_cache.eql?(:header)
129
- 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]
130
132
  # return @api_node.read("files/#{file_id}/files",request_args)[:data]
131
133
  end
132
134
 
@@ -151,11 +153,11 @@ module Aspera
151
153
  end
152
154
  return if events.empty?
153
155
  events.each do |event|
154
- if event['data']['direction'].eql?(Fasp::TransferSpec::DIRECTION_RECEIVE) &&
156
+ if event['data']['direction'].eql?(Transfer::Spec::DIRECTION_RECEIVE) &&
155
157
  event['data']['status'].eql?('completed') &&
156
158
  event['data']['error_code'].eql?(0) &&
157
- event['data'].dig('tags', Fasp::TransferSpec::TAG_RESERVED, PREV_GEN_TAG).nil?
158
- 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')
159
161
  folder_id ||= event.dig('data', 'file_id')
160
162
  if !folder_id.nil?
161
163
  folder_entry = @api_node.read("files/#{folder_id}")[:data] rescue nil
@@ -189,7 +191,7 @@ module Aspera
189
191
  if event.dig('data', 'type').eql?('file')
190
192
  file_entry = @api_node.read("files/#{event['data']['id']}")[:data] rescue nil
191
193
  if !file_entry.nil? &&
192
- @option_skip_folders.select{|d|file_entry['path'].start_with?(d)}.empty?
194
+ @option_skip_folders.none?{|d|file_entry['path'].start_with?(d)}
193
195
  file_entry['parent_file_id'] = event['data']['parent_file_id']
194
196
  if event['types'].include?('file.deleted')
195
197
  Log.log.error('TODO'.red)
@@ -211,10 +213,10 @@ module Aspera
211
213
  end
212
214
 
213
215
  def do_transfer(direction, folder_id, source_filename, destination='/')
214
- raise 'Internal ERROR' if destination.nil? && direction.eql?(Fasp::TransferSpec::DIRECTION_RECEIVE)
216
+ Aspera.assert(!(destination.nil? && direction.eql?(Transfer::Spec::DIRECTION_RECEIVE)))
215
217
  t_spec = @api_node.transfer_spec_gen4(folder_id, direction, {
216
218
  'paths' => [{'source' => source_filename}],
217
- 'tags' => {Fasp::TransferSpec::TAG_RESERVED => {PREV_GEN_TAG => true}}
219
+ 'tags' => {Transfer::Spec::TAG_RESERVED => {PREV_GEN_TAG => true}}
218
220
  })
219
221
  # force destination, need to set this in transfer agent else it gets overwritten, not do: t_spec['destination_root']=destination
220
222
  transfer.option_transfer_spec_deep_merge({'destination_root' => destination})
@@ -316,7 +318,7 @@ module Aspera
316
318
  if @access_remote
317
319
  raise 'missing parent_file_id in entry' if entry['parent_file_id'].nil?
318
320
  # download original file to temp folder
319
- 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)
320
322
  end
321
323
  Log.log.info{"source: #{entry['id']}: #{entry['path']}"}
322
324
  gen_infos.each do |gen_info|
@@ -324,7 +326,7 @@ module Aspera
324
326
  end
325
327
  if @access_remote
326
328
  # upload
327
- 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)
328
330
  # cleanup after upload
329
331
  FileUtils.rm_rf(local_entry_preview_dir)
330
332
  File.delete(File.join(@tmp_folder, entry['name']))
@@ -401,8 +403,8 @@ module Aspera
401
403
  command = options.get_next_command(ACTIONS)
402
404
  unless %i[check test show].include?(command)
403
405
  # this will use node api
404
- @api_node = Aspera::Node.new(params: basic_auth_params)
405
- @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
406
408
  # get current access key
407
409
  @access_key_self = @api_node.read('access_keys/self')[:data]
408
410
  # TODO: check events is activated here:
@@ -420,13 +422,13 @@ module Aspera
420
422
  raise Cli::Error, "Folder #{@option_previews_folder} does not exist on node. " \
421
423
  'Please create it in the storage root, or specify an alternate name.' if @previews_folder_entry.nil?
422
424
  else
423
- raise 'only local storage allowed in this mode' unless @access_key_self['storage']['type'].eql?('local')
425
+ Aspera.assert(@access_key_self['storage']['type'].eql?('local')){'only local storage allowed in this mode'}
424
426
  @local_storage_root = @access_key_self['storage']['path']
425
427
  # TODO: option to override @local_storage_root='xxx'
426
428
  @local_storage_root = @local_storage_root[PVCL_LOCAL_STORAGE.length..-1] if @local_storage_root.start_with?(PVCL_LOCAL_STORAGE)
427
429
  # TODO: windows could have "C:" ?
428
- raise "not local storage: #{@local_storage_root}" unless @local_storage_root.start_with?('/')
429
- raise Cli::Error, "Local storage root folder #{@local_storage_root} does not exist." unless File.directory?(@local_storage_root)
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."}
430
432
  @local_preview_folder = File.join(@local_storage_root, @option_previews_folder)
431
433
  raise Cli::Error, "Folder #{@local_preview_folder} does not exist locally. " \
432
434
  'Please create it, or specify an alternate name.' unless File.directory?(@local_preview_folder)
@@ -435,7 +437,7 @@ module Aspera
435
437
  Log.log.debug{"marker file: #{marker_file}"}
436
438
  if File.exist?(marker_file)
437
439
  ak = File.read(marker_file).chomp
438
- raise "mismatch access key in #{marker_file}: contains #{ak}, using #{@access_key_self['id']}" unless @access_key_self['id'].eql?(ak)
440
+ Aspera.assert(@access_key_self['id'].eql?(ak)){"mismatch access key in #{marker_file}: contains #{ak}, using #{@access_key_self['id']}"}
439
441
  else
440
442
  File.write(marker_file, @access_key_self['id'])
441
443
  end
@@ -459,15 +461,15 @@ module Aspera
459
461
  else
460
462
  @api_node.read("files/#{scan_id}")[:data]
461
463
  end
462
- @filter_block = Aspera::Node.file_matcher_from_argument(options)
464
+ @filter_block = Api::Node.file_matcher_from_argument(options)
463
465
  scan_folder_files(folder_info, scan_path)
464
466
  return Main.result_status('scan finished')
465
467
  when :events, :trevents
466
- @filter_block = Aspera::Node.file_matcher_from_argument(options)
468
+ @filter_block = Api::Node.file_matcher_from_argument(options)
467
469
  iteration_persistency = nil
468
470
  if options.get_option(:once_only, mandatory: true)
469
471
  iteration_persistency = PersistencyActionOnce.new(
470
- manager: @agents[:persistency],
472
+ manager: persistency,
471
473
  data: [],
472
474
  id: IdGenerator.from_list([
473
475
  'preview_iteration',
@@ -477,7 +479,7 @@ module Aspera
477
479
  ]))
478
480
  end
479
481
  # call processing method specified by command line command
480
- send("process_#{command}", iteration_persistency)
482
+ send(:"process_#{command}", iteration_persistency)
481
483
  return Main.result_status("#{command} finished")
482
484
  when :check
483
485
  return Main.result_status('Tools validated')
@@ -499,8 +501,8 @@ module Aspera
499
501
  ensure
500
502
  Log.log.debug{"cleaning up temp folder #{@tmp_folder}"}
501
503
  FileUtils.rm_rf(@tmp_folder)
502
- end # execute_action
503
- end # Preview
504
- end # Plugins
505
- end # Cli
506
- end # Aspera
504
+ end
505
+ end
506
+ end
507
+ end
508
+ end
@@ -3,10 +3,12 @@
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'
10
+ require 'aspera/log'
11
+ require 'aspera/assert'
10
12
  require 'tempfile'
11
13
  require 'open3'
12
14
 
@@ -14,7 +16,7 @@ module Aspera
14
16
  module Cli
15
17
  module Plugins
16
18
  # implement basic remote access with FASP/SSH
17
- class Server < Aspera::Cli::BasicAuthPlugin
19
+ class Server < Cli::BasicAuthPlugin
18
20
  include SyncActions
19
21
  SSH_SCHEME = 'ssh'
20
22
  LOCAL_SCHEME = 'local'
@@ -51,27 +53,27 @@ module Aspera
51
53
  [address_or_url]
52
54
  else
53
55
  [
54
- "ssh://#{address_or_url}:33001",
55
- "ssh://#{address_or_url}:22"
56
+ "#{SSH_SCHEME}://#{address_or_url}:33001",
57
+ "#{SSH_SCHEME}://#{address_or_url}:22"
56
58
  ]
57
59
  # wss not practical as it requires a token
58
60
  end
59
-
61
+ error = nil
60
62
  urls.each do |base_url|
61
63
  server_uri = URI.parse(base_url)
62
64
  Log.log.debug{"URI=#{server_uri}, host=#{server_uri.hostname}, port=#{server_uri.port}, scheme=#{server_uri.scheme}"}
63
65
  next unless server_uri.scheme.eql?(SSH_SCHEME)
64
- begin
65
- socket = TCPSocket.new(server_uri.hostname, server_uri.port)
66
- socket.puts('SSH-2.0-Ascli_0.0')
67
- version = socket.gets.chomp
68
- if version.match?(/^SSH-2.0-/)
69
- return {version: version.gsub(/^SSH-2.0-/, ''), url: base_url}
70
- end
71
- rescue StandardError => e
72
- 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}
73
71
  end
72
+ rescue StandardError => e
73
+ error = e
74
+ Log.log.debug{"detect error: #{e}"}
74
75
  end
76
+ raise error if error
75
77
  return nil
76
78
  end
77
79
 
@@ -88,8 +90,8 @@ module Aspera
88
90
  end
89
91
  end
90
92
 
91
- def initialize(env)
92
- super(env)
93
+ def initialize(**env)
94
+ super
93
95
  options.declare(:ssh_keys, 'SSH key path list (Array or single)')
94
96
  options.declare(:passphrase, 'SSH private key passphrase')
95
97
  options.declare(:ssh_options, 'SSH options', types: Hash, default: {})
@@ -125,14 +127,14 @@ module Aspera
125
127
  if !server_uri.scheme.eql?(SSH_SCHEME)
126
128
  Log.log.warn('URL scheme is https but no token was provided in transfer spec.')
127
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")
128
- 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}"
129
131
  Log.log.warn{"Assuming proper URL is: #{assumed_url}"}
130
132
  server_uri = URI.parse(assumed_url)
131
133
  end
132
134
  # Scheme is SSH
133
135
  if options.get_option(:username).nil?
134
- options.set_option(:username, Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER)
135
- 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}"}
136
138
  end
137
139
  server_transfer_spec['remote_user'] = options.get_option(:username, mandatory: true)
138
140
  if !server_uri.port.nil?
@@ -148,16 +150,15 @@ module Aspera
148
150
  end
149
151
  ssh_key_list = options.get_option(:ssh_keys)
150
152
  if !ssh_key_list.nil?
151
- raise 'Expecting single value or array for ssh_keys' unless ssh_key_list.is_a?(Array) || ssh_key_list.is_a?(String)
152
153
  ssh_key_list = [ssh_key_list] if ssh_key_list.is_a?(String)
154
+ Aspera.assert_type(ssh_key_list, Array){'ssh_keys'}
155
+ Aspera.assert(ssh_key_list.all?(String))
153
156
  ssh_key_list.map!{|p|File.expand_path(p)}
154
157
  Log.log.debug{"SSH keys=#{ssh_key_list}"}
155
158
  if !ssh_key_list.empty?
156
159
  @ssh_opts[:keys] = ssh_key_list
157
- server_transfer_spec['EX_ssh_key_paths'] = ssh_key_list
158
- ssh_key_list.each do |k|
159
- Log.log.warn{"No such key file: #{k}"} unless File.exist?(k)
160
- 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)
161
162
  cred_set = true
162
163
  end
163
164
  end
@@ -175,7 +176,7 @@ module Aspera
175
176
  def execute_transfer(command, transfer_spec)
176
177
  case command
177
178
  when :upload, :download
178
- Fasp::TransferSpec.action_to_direction(transfer_spec, command)
179
+ Transfer::Spec.action_to_direction(transfer_spec, command)
179
180
  return Main.result_transfer(transfer.start(transfer_spec))
180
181
  when :sync
181
182
  # lets ignore the arguments provided by execute_sync_action, we just give the transfer spec
@@ -186,7 +187,7 @@ module Aspera
186
187
  # actions without ascmd
187
188
  BASE_ACTIONS = %i[health].concat(TRANSFER_COMMANDS).freeze
188
189
  # all actions
189
- ACTIONS = [BASE_ACTIONS, Aspera::AsCmd::OPERATIONS, ASCMD_ALIASES.keys].flatten.freeze
190
+ ACTIONS = [BASE_ACTIONS, AsCmd::OPERATIONS, ASCMD_ALIASES.keys].flatten.freeze
190
191
 
191
192
  def execute_action
192
193
  server_transfer_spec = options_to_base_transfer_spec
@@ -225,16 +226,16 @@ module Aspera
225
226
  else
226
227
  nagios.add_critical('transfer', statuses.reject{|i|i.eql?(:success)}.first.to_s)
227
228
  end
228
- else raise 'ERROR'
229
+ else Aspera.error_unexpected_value(command_nagios)
229
230
  end
230
231
  return nagios.result
231
232
  when *TRANSFER_COMMANDS
232
233
  return execute_transfer(command, server_transfer_spec)
233
- when *Aspera::AsCmd::OPERATIONS
234
+ when *AsCmd::OPERATIONS
234
235
  command_arguments = options.get_next_argument('ascmd command arguments', expected: :multiple, mandatory: false)
235
- ascmd = Aspera::AsCmd.new(ascmd_executor)
236
+ ascmd = AsCmd.new(ascmd_executor)
236
237
  begin
237
- result = ascmd.send(:execute_single, command, command_arguments)
238
+ result = ascmd.execute_single(command, command_arguments)
238
239
  case command
239
240
  when :mkdir, :mv, :cp, :rm
240
241
  return Main.result_success
@@ -245,10 +246,10 @@ module Aspera
245
246
  when :du, :md5sum, :info
246
247
  return {type: :single_object, data: result.stringify_keys}
247
248
  end
248
- rescue Aspera::AsCmd::Error => e
249
+ rescue AsCmd::Error => e
249
250
  raise Cli::BadArgument, e.extended_message
250
251
  end
251
- else raise 'internal error: unexpected action'
252
+ else Aspera.error_unreachable_line
252
253
  end
253
254
  end # execute_action
254
255
  end # Server
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'aspera/cli/plugins/node'
4
-
4
+ require 'aspera/assert'
5
5
  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,10 +47,8 @@ module Aspera
47
47
  end
48
48
  end
49
49
 
50
- def initialize(env)
51
- super(env)
52
- options.declare(:type, 'Type of user/group for operations', values: %i[any local ldap saml], default: :any)
53
- options.parse_options!
50
+ def initialize(**env)
51
+ super
54
52
  end
55
53
 
56
54
  SAML_IMPORT_MANDATORY = %w[id name_id].freeze
@@ -81,66 +79,74 @@ module Aspera
81
79
  when :repository, :files
82
80
  api_shares_node = basic_auth_api(API_BASE)
83
81
  repo_command = options.get_next_command(Node::COMMANDS_SHARES)
84
- 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)
85
83
  when :admin
86
84
  api_shares_admin = basic_auth_api('api/v1')
87
- admin_command = options.get_next_command(%i[user group share node].freeze)
85
+ admin_command = options.get_next_command(%i[node share transfer_settings user group].freeze)
88
86
  case admin_command
89
87
  when :node
90
88
  return entity_action(api_shares_admin, 'data/nodes')
89
+ when :share
90
+ share_command = options.get_next_command(%i[user_permissions group_permissions].concat(Plugin::ALL_OPS))
91
+ case share_command
92
+ when *Plugin::ALL_OPS
93
+ return entity_command(share_command, api_shares_admin, 'data/shares')
94
+ # return {type: :object_list, data: all_shares, fields: %w[id name status status_message]}
95
+ when :user_permissions, :group_permissions
96
+ share_id = instance_identifier
97
+ return entity_action(api_shares_admin, "data/shares/#{share_id}/#{share_command}")
98
+ end
99
+ when :transfer_settings
100
+ xfer_settings_command = options.get_next_command(%i[show modify])
101
+ return entity_command(xfer_settings_command, api_shares_admin, 'data/transfer_settings', is_singleton: true)
91
102
  when :user, :group
92
103
  entity_type = admin_command
93
- entities_location = options.get_option(:type, mandatory: true)
94
- entities_path = "data/#{entities_location}_#{entity_type}s"
104
+ entities_location = options.get_next_command(%i[all local ldap saml])
105
+ entities_prefix = entities_location.eql?(:all) ? '' : "#{entities_location}_"
106
+ entities_path = "data/#{entities_prefix}#{entity_type}s"
95
107
  entity_action = nil
96
108
  case entities_location
97
- when :any
98
- entities_path = "data/#{entity_type}s"
109
+ when :all
99
110
  entity_action = %i[list show delete]
100
111
  entity_action.concat(USR_GRP_SETTINGS)
101
112
  entity_action.push(:users) if entity_type.eql?(:group)
102
113
  entity_action.freeze
103
114
  when :local
104
- entity_action = %i[list show create modify delete].freeze
115
+ entity_action = %i[list show delete create modify]
116
+ entity_action.push(:users) if entity_type.eql?(:group)
117
+ entity_action.freeze
105
118
  when :ldap
106
119
  entity_action = %i[add].freeze
107
120
  when :saml
108
121
  entity_action = %i[import].freeze
109
122
  end
110
123
  entity_verb = options.get_next_command(entity_action)
111
- # entity_path = "#{entities_path}/#{instance_identifier}" if %i[app_authorizations share_permissions].include?(entity_verb)
112
124
  case entity_verb
113
- when *Plugin::ALL_OPS
125
+ when *Plugin::ALL_OPS # list, show, delete, create, modify
114
126
  display_fields = entity_type.eql?(:user) ? %w[id username first_name last_name email] : nil
115
- display_fields.push(:directory_user) if entity_type.eql?(:user) && entities_location.eql?(:any)
127
+ display_fields.push(:directory_user) if entity_type.eql?(:user) && entities_location.eql?(:all)
116
128
  return entity_command(entity_verb, api_shares_admin, entities_path, display_fields: display_fields)
117
- when :import
129
+ when *USR_GRP_SETTINGS # transfer_settings, app_authorizations, share_permissions
130
+ group_id = instance_identifier
131
+ entities_path = "#{entities_path}/#{group_id}/#{entity_verb}"
132
+ return entity_action(api_shares_admin, entities_path, is_singleton: !entity_verb.eql?(:share_permissions))
133
+ when :import # saml
118
134
  return do_bulk_operation(command: entity_verb, descr: 'user information') do |entity_parameters|
119
135
  entity_parameters = entity_parameters.transform_keys{|k|k.gsub(/\s+/, '_').downcase}
120
- raise 'expecting Hash' unless entity_parameters.is_a?(Hash)
136
+ Aspera.assert_type(entity_parameters, Hash)
121
137
  SAML_IMPORT_MANDATORY.each{|p|raise "missing mandatory field: #{p}" if entity_parameters[p].nil?}
122
138
  entity_parameters.each_key do |p|
123
139
  raise "unsupported field: #{p}, use: #{SAML_IMPORT_ALLOWED.join(',')}" unless SAML_IMPORT_ALLOWED.include?(p)
124
140
  end
125
141
  api_shares_admin.create("#{entities_path}/import", entity_parameters)[:data]
126
142
  end
127
- when :add
143
+ when :add # ldap
128
144
  return do_bulk_operation(command: entity_verb, descr: "#{entity_type} name", values: String) do |entity_name|
129
145
  api_shares_admin.create(entities_path, {entity_type=>entity_name})[:data]
130
146
  end
131
- when *USR_GRP_SETTINGS
132
- group_id = instance_identifier
133
- entities_path = "#{entities_path}/#{group_id}/#{entity_verb}"
134
- return entity_action(api_shares_admin, entities_path, is_singleton: !entity_verb.eql?(:share_permissions))
135
- end
136
- when :share
137
- share_command = options.get_next_command(%i[user_permissions group_permissions].concat(Plugin::ALL_OPS))
138
- case share_command
139
- when *Plugin::ALL_OPS
140
- return entity_command(share_command, api_shares_admin, 'data/shares')
141
- # return {type: :object_list, data: all_shares, fields: %w[id name status status_message]}
142
- when :user_permissions, :group_permissions
143
- return entity_action(api_shares_admin, "data/shares/#{instance_identifier}/#{share_command}")
147
+ when :users # group
148
+ return entity_action(api_shares_admin, "#{entities_path}/#{instance_identifier}/#{entities_prefix}users")
149
+ else Aspera.error_unexpected_value(entity_verb)
144
150
  end
145
151
  end
146
152
  end
@@ -1,13 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'aspera/sync'
3
+ require 'aspera/transfer/sync'
4
+ require 'aspera/assert'
4
5
 
5
6
  module Aspera
6
7
  module Cli
7
8
  # Module for sync actions
8
9
  module SyncActions
9
10
  SIMPLE_ARGUMENTS_SYNC = {
10
- direction: Aspera::Sync::DIRECTIONS,
11
+ direction: Transfer::Sync::DIRECTIONS,
11
12
  local_dir: String,
12
13
  remote_dir: String
13
14
  }.stringify_keys.freeze
@@ -19,8 +20,7 @@ module Aspera
19
20
  end
20
21
 
21
22
  def execute_sync_action(&block)
22
- # options = Aspera::Cli::Manager.new
23
- raise 'Internal Error: No block given' unless block
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
- raise "sync_info shall be a Hash with key 'sessions' with Array of Hash: #{async_params}" unless async_params.is_a?(Hash) &&
49
- async_params['sessions']&.is_a?(Array) &&
50
- async_params['sessions'].first.is_a?(Hash)
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::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::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