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
data/lib/aspera/assert.rb CHANGED
@@ -6,40 +6,40 @@ module Aspera
6
6
 
7
7
  class AssertError < StandardError
8
8
  end
9
- end
10
-
11
- class Object
12
- def assert(assertion, info = nil, level: 2, exception_class: Aspera::AssertError)
13
- raise Aspera::InternalError, 'bad assert: both info and block given' unless info.nil? || !block_given?
14
- return if assertion
15
- message = 'assertion failed'
16
- info = yield if block_given?
17
- message = "#{message}: #{info}" if info
18
- message = "#{message}: #{caller(level..level).first}"
19
- raise exception_class, message
20
- end
9
+ class << self
10
+ # the block is executed in the context of the Aspera module
11
+ def assert(assertion, info = nil, level: 2, exception_class: AssertError)
12
+ raise InternalError, 'bad assert: both info and block given' unless info.nil? || !block_given?
13
+ return if assertion
14
+ message = 'assertion failed'
15
+ info = yield if block_given?
16
+ message = "#{message}: #{info}" if info
17
+ message = "#{message}: #{caller(level..level).first}"
18
+ raise exception_class, message
19
+ end
21
20
 
22
- # assert that value has the given type
23
- # @param value [Object] the value to check
24
- # @param type [Class] the expected type
25
- def assert_type(value, type, exception_class: Aspera::AssertError)
26
- assert(value.is_a?(type), level: 3, exception_class: exception_class){"#{block_given? ? "#{yield}: " : nil}expecting #{type}, but have #{value.inspect}"}
27
- end
21
+ # assert that value has the given type
22
+ # @param value [Object] the value to check
23
+ # @param type [Class] the expected type
24
+ def assert_type(value, type, exception_class: AssertError)
25
+ assert(value.is_a?(type), level: 3, exception_class: exception_class){"#{block_given? ? "#{yield}: " : nil}expecting #{type}, but have #{value.inspect}"}
26
+ end
28
27
 
29
- # assert that value is one of the given values
30
- def assert_values(value, values, exception_class: Aspera::AssertError)
31
- assert(values.include?(value), level: 3, exception_class: exception_class) do
32
- "#{block_given? ? "#{yield}: " : nil}expecting one of #{values.inspect}, but have #{value.inspect}"
28
+ # assert that value is one of the given values
29
+ def assert_values(value, values, exception_class: AssertError)
30
+ assert(values.include?(value), level: 3, exception_class: exception_class) do
31
+ "#{block_given? ? "#{yield}: " : nil}expecting one of #{values.inspect}, but have #{value.inspect}"
32
+ end
33
33
  end
34
- end
35
34
 
36
- # the line with this shall never be reached
37
- def error_unreachable_line
38
- raise Aspera::InternalError, "unreachable line reached: #{caller(2..2).first}"
39
- end
35
+ # the line with this shall never be reached
36
+ def error_unreachable_line
37
+ raise InternalError, "unreachable line reached: #{caller(2..2).first}"
38
+ end
40
39
 
41
- # the value is not one of the expected values
42
- def error_unexpected_value(value, exception_class: Aspera::InternalError)
43
- raise exception_class, "#{block_given? ? "#{yield}: " : nil}unexpected value: #{value.inspect}"
40
+ # the value is not one of the expected values
41
+ def error_unexpected_value(value, exception_class: InternalError)
42
+ raise exception_class, "#{block_given? ? "#{yield}: " : nil}unexpected value: #{value.inspect}"
43
+ end
44
44
  end
45
45
  end
@@ -6,22 +6,23 @@ require 'aspera/cli/plugin'
6
6
  module Aspera
7
7
  module Cli
8
8
  # base class for applications supporting basic authentication
9
- class BasicAuthPlugin < Aspera::Cli::Plugin
9
+ class BasicAuthPlugin < Cli::Plugin
10
10
  class << self
11
- @@basic_options_declared = false # rubocop:disable Style/ClassVars
12
- def declare_options(options, force: false)
13
- return if @@basic_options_declared && !force
14
- @@basic_options_declared = true # rubocop:disable Style/ClassVars
11
+ #@@basic_options_declared = false # rubocop:disable Style/ClassVars
12
+ def declare_options(options) # , force: false
13
+ #return if @@basic_options_declared && !force
14
+ #@@basic_options_declared = true # rubocop:disable Style/ClassVars
15
15
  options.declare(:url, 'URL of application, e.g. https://faspex.example.com/aspera/faspex')
16
- options.declare(:username, 'Username to log in')
16
+ options.declare(:username, "User's name to log in")
17
17
  options.declare(:password, "User's password")
18
18
  options.parse_options!
19
19
  end
20
20
  end
21
21
 
22
- def initialize(env)
23
- super(env)
24
- BasicAuthPlugin.declare_options(options, force: env[:all_manuals])
22
+ def initialize(basic_options: true, **env)
23
+ super(**env)
24
+ # , force: env[:all_manuals]
25
+ BasicAuthPlugin.declare_options(options) if basic_options
25
26
  end
26
27
 
27
28
  # returns a Rest object with basic auth
@@ -38,7 +39,7 @@ module Aspera
38
39
  end
39
40
 
40
41
  def basic_auth_api(subpath=nil)
41
- return Rest.new(basic_auth_params(subpath))
42
+ return Rest.new(**basic_auth_params(subpath))
42
43
  end
43
44
  end # BasicAuthPlugin
44
45
  end # Cli
@@ -78,7 +78,7 @@ module Aspera
78
78
  # add a new handler
79
79
  def set_handler(name, method)
80
80
  Log.log.debug{"setting handler for #{name}"}
81
- assert_type(name, Symbol){'name'}
81
+ Aspera.assert_type(name, Symbol){'name'}
82
82
  @handlers[name] = method
83
83
  end
84
84
 
@@ -20,7 +20,7 @@ module Aspera
20
20
 
21
21
  # General method
22
22
  def flatten(something)
23
- assert_type(something, Hash)
23
+ Aspera.assert_type(something, Hash)
24
24
  @result = {}
25
25
  flatten_any(something, '')
26
26
  return @result
@@ -107,7 +107,7 @@ module Aspera
107
107
  class << self
108
108
  # Highlight special values
109
109
  def special(what, use_colors: $stdout.isatty)
110
- result = "<#{what}>"
110
+ result = $stdout.isatty ? "<#{what}>" : "&lt;#{what}&gt;"
111
111
  if use_colors
112
112
  result = if %w[null empty].any?{|s|what.include?(s)}
113
113
  result.dim
@@ -158,7 +158,7 @@ module Aspera
158
158
  end
159
159
 
160
160
  def option_handler(option_symbol, operation, value=nil)
161
- assert_values(operation, %i[set get])
161
+ Aspera.assert_values(operation, %i[set get])
162
162
  case operation
163
163
  when :set
164
164
  @options[option_symbol] = value
@@ -170,7 +170,7 @@ module Aspera
170
170
  end
171
171
  end
172
172
  when :get then return @options[option_symbol]
173
- else error_unreachable_line
173
+ else Aspera.error_unreachable_line
174
174
  end
175
175
  nil
176
176
  end
@@ -199,7 +199,7 @@ module Aspera
199
199
  when :data then $stdout.puts(message) unless @options[:display].eql?(:error)
200
200
  when :info then $stdout.puts(message) if @options[:display].eql?(:info)
201
201
  when :error then $stderr.puts(message)
202
- else error_unexpected_value(message_level)
202
+ else Aspera.error_unexpected_value(message_level)
203
203
  end
204
204
  end
205
205
 
@@ -232,7 +232,7 @@ module Aspera
232
232
  when Array then @options[:fields]
233
233
  when Regexp then return all_fields(data).select{|i|i.match(@options[:fields])}
234
234
  when Proc then return all_fields(data).select{|i|@options[:fields].call(i)}
235
- else error_unexpected_value(@options[:fields])
235
+ else Aspera.error_unexpected_value(@options[:fields])
236
236
  end
237
237
  result = []
238
238
  until request.empty?
@@ -265,7 +265,7 @@ module Aspera
265
265
  # object_array: array of hash
266
266
  # fields: list of column names
267
267
  def display_table(object_array, fields)
268
- assert(!fields.nil?){'missing fields parameter'}
268
+ Aspera.assert(!fields.nil?){'missing fields parameter'}
269
269
  case @options[:select]
270
270
  when Proc
271
271
  object_array.select!{|i|@options[:select].call(i)}
@@ -309,10 +309,10 @@ module Aspera
309
309
 
310
310
  # this method displays the results, especially the table format
311
311
  def display_results(results)
312
- assert_type(results, Hash)
313
- assert((results.keys - RESULT_PARAMS).empty?){"result unsupported key: #{results.keys - RESULT_PARAMS}"}
314
- assert(results.key?(:type)){"result must have type (#{results})"}
315
- assert(results.key?(:data) || %i[empty nothing].include?(results[:type])){'result must have data'}
312
+ Aspera.assert_type(results, Hash)
313
+ Aspera.assert((results.keys - RESULT_PARAMS).empty?){"result unsupported key: #{results.keys - RESULT_PARAMS}"}
314
+ Aspera.assert(results.key?(:type)){"result must have type (#{results})"}
315
+ Aspera.assert(results.key?(:data) || %i[empty nothing].include?(results[:type])){'result must have data'}
316
316
  Log.log.debug{"display_results: #{results[:data].class} #{results[:type]}"}
317
317
  display_item_count(results[:data].length, results[:total]) if results.key?(:total)
318
318
  SecretHider.deep_remove_secret(results[:data]) unless @options[:show_secrets] || @options[:display].eql?(:data)
@@ -336,8 +336,8 @@ module Aspera
336
336
  when :object_list, :single_object
337
337
  obj_list = results[:data]
338
338
  obj_list = [obj_list] if results[:type].eql?(:single_object)
339
- assert_type(obj_list, Array)
340
- assert(obj_list.all?(Hash)){"expecting Array of Hash: #{obj_list.inspect}"}
339
+ Aspera.assert_type(obj_list, Array)
340
+ Aspera.assert(obj_list.all?(Hash)){"expecting Array of Hash: #{obj_list.inspect}"}
341
341
  # :object_list is an array of hash tables, where key=colum name
342
342
  obj_list = obj_list.map{|obj|Flattener.new.flatten(obj)} if @options[:flat_hash]
343
343
  display_table(obj_list, compute_fields(obj_list, results[:fields]))
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'aspera/fasp/error'
3
+ require 'aspera/transfer/error'
4
4
  require 'aspera/rest'
5
5
  require 'aspera/log'
6
6
  require 'aspera/assert'
@@ -14,7 +14,7 @@ module Aspera
14
14
  # Well know issues that users may get
15
15
  ERROR_HINTS = [
16
16
  {
17
- exception: Fasp::Error,
17
+ exception: Transfer::Error,
18
18
  match: 'Remote host is not who we expected',
19
19
  remediation: [
20
20
  'For this specific error, refer to:',
@@ -24,7 +24,7 @@ module Aspera
24
24
  ]
25
25
  },
26
26
  {
27
- exception: Aspera::RestCallError,
27
+ exception: RestCallError,
28
28
  match: /Signature has expired/,
29
29
  remediation: [
30
30
  'There is too much time difference between your computer and the server',
@@ -60,13 +60,13 @@ module Aspera
60
60
  matches = hint[:match]
61
61
  matches = [matches] unless matches.is_a?(Array)
62
62
  matches.each do |m|
63
- assert_values(m.class, [String, Regexp])
63
+ Aspera.assert_values(m.class, [String, Regexp])
64
64
  case m
65
65
  when String
66
66
  next unless message.eql?(m)
67
67
  when Regexp
68
68
  next unless message.match?(m)
69
- else error_unexpected_value(m)
69
+ else Aspera.error_unexpected_value(m)
70
70
  end
71
71
  remediation = hint[:remediation]
72
72
  remediation = [remediation] unless remediation.is_a?(Array)
@@ -4,6 +4,7 @@ require 'aspera/cli/manager'
4
4
  require 'aspera/cli/formatter'
5
5
  require 'aspera/cli/plugins/config'
6
6
  require 'aspera/cli/extended_value'
7
+ require 'aspera/cli/plugin_factory'
7
8
  require 'aspera/cli/transfer_agent'
8
9
  require 'aspera/cli/version'
9
10
  require 'aspera/cli/info'
@@ -19,6 +20,9 @@ module Aspera
19
20
  class Main
20
21
  # Plugins store transfer result using this key and use result_transfer_multiple()
21
22
  STATUS_FIELD = 'status'
23
+ CONF_PLUGIN_SYM = :config
24
+
25
+ private_constant :CONF_PLUGIN_SYM
22
26
 
23
27
  class << self
24
28
  # expect some list, but nothing to display
@@ -69,7 +73,7 @@ module Aspera
69
73
 
70
74
  # shortcuts helpers like in plugins
71
75
  %i[options transfer config formatter persistency].each do |name|
72
- define_method(name){@agents[name]}
76
+ define_method(name){@plug_init[name]}
73
77
  end
74
78
 
75
79
  # =============================================================
@@ -80,7 +84,7 @@ module Aspera
80
84
  def initialize(argv)
81
85
  @argv = argv
82
86
  # environment provided to plugin for various capabilities
83
- @agents = {}
87
+ @plug_init = Plugin::INIT_PARAMS.each_with_object({}) { |key, hash| hash[key] = nil }
84
88
  @option_help = false
85
89
  @option_show_config = false
86
90
  @bash_completion = false
@@ -88,11 +92,12 @@ module Aspera
88
92
 
89
93
  # This can throw exception if there is a problem with the environment, needs to be caught by execute method
90
94
  def init_agents_and_options
95
+ @plug_init[:only_manual] = false
91
96
  # create formatter, in case there is an exception, it is used to display.
92
- @agents[:formatter] = Formatter.new
97
+ @plug_init[:formatter] = Formatter.new
93
98
  # second : manage debug level (allows debugging of option parser)
94
99
  early_debug_setup
95
- @agents[:options] = Manager.new(PROGRAM_NAME)
100
+ @plug_init[:options] = Manager.new(PROGRAM_NAME)
96
101
  # give command line arguments to option manager
97
102
  options.parse_command_line(@argv)
98
103
  # formatter adds options
@@ -105,11 +110,14 @@ module Aspera
105
110
  # declare and parse global options
106
111
  declare_global_options
107
112
  # the Config plugin adds the @preset parser, so declare before TransferAgent which may use it
108
- @agents[:config] = Plugins::Config.new(@agents, gem: GEM_NAME, name: PROGRAM_NAME, help: DOC_URL, version: Aspera::Cli::VERSION)
113
+ @plug_init[:config] = Plugins::Config.new(**@plug_init, gem: GEM_NAME, name: PROGRAM_NAME, help: DOC_URL, version: Cli::VERSION)
114
+ @plug_init[:persistency] = @plug_init[:config].persistency
109
115
  # data persistency
110
- assert(@agents[:persistency]){'missing persistency object'}
116
+ Aspera.assert(@plug_init[:persistency]){'missing persistency object'}
111
117
  # the TransferAgent plugin may use the @preset parser
112
- @agents[:transfer] = TransferAgent.new(options, config)
118
+ @plug_init[:config].transfer = @plug_init[:transfer] = TransferAgent.new(options, config)
119
+ nil_keys = @plug_init.select{|_, value|value.nil?}.keys
120
+ Aspera.assert(nil_keys.empty?){"nil : #{nil_keys}"}
113
121
  Log.log.debug('plugin env created'.red)
114
122
  # set banner when all environment is created so that additional extended value modifiers are known, e.g. @preset
115
123
  options.parser.banner = app_banner
@@ -119,7 +127,7 @@ module Aspera
119
127
  t = ' ' * 8
120
128
  return <<~END_OF_BANNER
121
129
  NAME
122
- #{t}#{PROGRAM_NAME} -- a command line tool for Aspera Applications (v#{Aspera::Cli::VERSION})
130
+ #{t}#{PROGRAM_NAME} -- a command line tool for Aspera Applications (v#{Cli::VERSION})
123
131
 
124
132
  SYNOPSIS
125
133
  #{t}#{PROGRAM_NAME} COMMANDS [OPTIONS] [ARGS]
@@ -155,7 +163,7 @@ module Aspera
155
163
  options.declare(:help, 'Show this message', values: :none, short: 'h') { @option_help = true }
156
164
  options.declare(:bash_comp, 'Generate bash completion for command', values: :none) { @bash_completion = true }
157
165
  options.declare(:show_config, 'Display parameters used for the provided action', values: :none) { @option_show_config = true }
158
- options.declare(:version, 'Display version', values: :none, short: 'v') { formatter.display_message(:data, Aspera::Cli::VERSION); Process.exit(0) } # rubocop:disable Style/Semicolon, Layout/LineLength
166
+ options.declare(:version, 'Display version', values: :none, short: 'v') { formatter.display_message(:data, Cli::VERSION); Process.exit(0) } # rubocop:disable Style/Semicolon, Layout/LineLength
159
167
  options.declare(:warnings, 'Check for language warnings', values: :none, short: 'w') { $VERBOSE = true }
160
168
  options.declare(
161
169
  :ui, 'Method to start browser',
@@ -177,20 +185,19 @@ module Aspera
177
185
  # also loads the plugin options, and default values from conf file
178
186
  # @param plugin_name_sym : symbol for plugin name
179
187
  def get_plugin_instance_with_options(plugin_name_sym, env=nil)
180
- env ||= @agents
188
+ env ||= @plug_init
181
189
  Log.log.debug{"get_plugin_instance_with_options(#{plugin_name_sym})"}
182
- require config.plugins[plugin_name_sym][:require_stanza]
190
+ require PluginFactory.instance.plugins[plugin_name_sym][:require_stanza]
183
191
  # load default params only if no param already loaded before plugin instantiation
184
192
  env[:config].add_plugin_default_preset(plugin_name_sym)
185
- command_plugin = Plugins::Config.plugin_class(plugin_name_sym).new(env)
193
+ command_plugin = PluginFactory.instance.create(plugin_name_sym, **env)
186
194
  Log.log.debug{"got #{command_plugin.class}"}
187
- # TODO: check that ancestor is Plugin?
188
195
  return command_plugin
189
196
  end
190
197
 
191
198
  def generate_bash_completion
192
199
  if options.get_next_argument('', expected: :multiple, mandatory: false).nil?
193
- config.plugins.each_key{|p|puts p.to_s}
200
+ PluginFactory.instance.plugins.each_key{|p|puts p}
194
201
  else
195
202
  Log.log.warn('only first level completion so far')
196
203
  end
@@ -203,11 +210,11 @@ module Aspera
203
210
  formatter.display_message(:error, options.parser)
204
211
  if all_plugins
205
212
  # list plugins that have a "require" field, i.e. all but main plugin
206
- config.plugins.each_key do |plugin_name_sym|
207
- next if plugin_name_sym.eql?(Plugins::Config::CONF_PLUGIN_SYM)
213
+ PluginFactory.instance.plugins.each_key do |plugin_name_sym|
214
+ next if plugin_name_sym.eql?(CONF_PLUGIN_SYM)
208
215
  # override main option parser with a brand new, to avoid having global options
209
- plugin_env = @agents.clone
210
- plugin_env[:all_manuals] = true # force declaration of all options
216
+ plugin_env = @plug_init.clone
217
+ plugin_env[:only_manual] = true # force declaration of all options
211
218
  plugin_env[:options] = Manager.new(PROGRAM_NAME)
212
219
  plugin_env[:options].parser.banner = '' # remove default banner
213
220
  get_plugin_instance_with_options(plugin_name_sym, plugin_env)
@@ -223,12 +230,12 @@ module Aspera
223
230
  # early debug for parser
224
231
  # Note: does not accept shortcuts
225
232
  def early_debug_setup
226
- Aspera::Log.instance.program_name = PROGRAM_NAME
233
+ Log.instance.program_name = PROGRAM_NAME
227
234
  @argv.each do |arg|
228
235
  case arg
229
236
  when '--' then break
230
- when /^--log-level=(.*)/ then Aspera::Log.instance.level = Regexp.last_match(1).to_sym
231
- when /^--logger=(.*)/ then Aspera::Log.instance.logger_type = Regexp.last_match(1).to_sym
237
+ when /^--log-level=(.*)/ then Log.instance.level = Regexp.last_match(1).to_sym
238
+ when /^--logger=(.*)/ then Log.instance.logger_type = Regexp.last_match(1).to_sym
232
239
  end
233
240
  rescue => e
234
241
  $stderr.puts("Error: #{e}")
@@ -247,16 +254,16 @@ module Aspera
247
254
  begin
248
255
  init_agents_and_options
249
256
  # find plugins, shall be after parse! ?
250
- config.add_plugins_from_lookup_folders
257
+ PluginFactory.instance.add_plugins_from_lookup_folders
251
258
  # help requested without command ? (plugins must be known here)
252
259
  exit_with_usage(true) if @option_help && options.command_or_arg_empty?
253
260
  generate_bash_completion if @bash_completion
254
261
  config.periodic_check_newer_gem_version
255
262
  command_sym =
256
263
  if @option_show_config && options.command_or_arg_empty?
257
- Plugins::Config::CONF_PLUGIN_SYM
264
+ CONF_PLUGIN_SYM
258
265
  else
259
- options.get_next_command(config.plugins.keys.dup.unshift(:help))
266
+ options.get_next_command(PluginFactory.instance.plugins.keys.dup.unshift(:help))
260
267
  end
261
268
  # command will not be executed, but we need manual
262
269
  options.fail_on_missing_mandatory = false if @option_help || @option_show_config
@@ -264,7 +271,7 @@ module Aspera
264
271
  case command_sym
265
272
  when :help
266
273
  exit_with_usage(true)
267
- when Plugins::Config::CONF_PLUGIN_SYM
274
+ when CONF_PLUGIN_SYM
268
275
  command_plugin = config
269
276
  else
270
277
  # get plugin, set options, etc
@@ -307,8 +314,8 @@ module Aspera
307
314
  rescue Cli::BadArgument => e; exception_info = {e: e, t: 'Argument', usage: true}
308
315
  rescue Cli::NoSuchIdentifier => e; exception_info = {e: e, t: 'Identifier'}
309
316
  rescue Cli::Error => e; exception_info = {e: e, t: 'Tool', usage: true}
310
- rescue Fasp::Error => e; exception_info = {e: e, t: 'Transfer'}
311
- rescue Aspera::RestCallError => e; exception_info = {e: e, t: 'Rest'}
317
+ rescue Transfer::Error => e; exception_info = {e: e, t: 'Transfer'}
318
+ rescue RestCallError => e; exception_info = {e: e, t: 'Rest'}
312
319
  rescue SocketError => e; exception_info = {e: e, t: 'Network'}
313
320
  rescue StandardError => e; exception_info = {e: e, t: "Other(#{e.class.name})", debug: true}
314
321
  rescue Interrupt => e; exception_info = {e: e, t: 'Interruption', debug: true}
@@ -317,7 +324,7 @@ module Aspera
317
324
  TempFileManager.instance.cleanup
318
325
  # 1- processing of error condition
319
326
  unless exception_info.nil?
320
- Log.log.warn(exception_info[:e].message) if Aspera::Log.instance.logger_type.eql?(:syslog) && exception_info[:security]
327
+ Log.log.warn(exception_info[:e].message) if Log.instance.logger_type.eql?(:syslog) && exception_info[:security]
321
328
  formatter.display_message(:error, "#{Formatter::ERROR_FLASH} #{exception_info[:t]}: #{exception_info[:e].message}")
322
329
  formatter.display_message(:error, 'Use option -h to get help.') if exception_info[:usage]
323
330
  # Is that a known error condition with proposal for remediation ?
@@ -21,7 +21,7 @@ module Aspera
21
21
  @option_name = option_name
22
22
  @has_writer = @object.respond_to?(writer_method)
23
23
  Log.log.debug{"AttrAccessor: #{@option_name}: #{@object.class}.#{@method}: writer=#{@has_writer}"}
24
- assert(@object.respond_to?(@method)) {"#{object} does not respond to #{method_name}"}
24
+ Aspera.assert(@object.respond_to?(@method)) {"#{object} does not respond to #{method_name}"}
25
25
  end
26
26
 
27
27
  def value
@@ -61,7 +61,7 @@ module Aspera
61
61
 
62
62
  class << self
63
63
  def enum_to_bool(enum)
64
- assert_values(enum, BOOLEAN_VALUES){'boolean'}
64
+ Aspera.assert_values(enum, BOOLEAN_VALUES){'boolean'}
65
65
  return TRUE_VALUES.include?(enum)
66
66
  end
67
67
 
@@ -75,8 +75,8 @@ module Aspera
75
75
  matching_exact = allowed_values.select{|i| i.to_s.eql?(short_value)}
76
76
  return matching_exact.first if matching_exact.length == 1
77
77
  matching = allowed_values.select{|i| i.to_s.start_with?(short_value)}
78
- multi_choice_assert(!matching.empty?,"unknown value for #{descr}: #{short_value}", allowed_values)
79
- multi_choice_assert(matching.length.eql?(1),"ambiguous shortcut for #{descr}: #{short_value}", matching)
78
+ multi_choice_assert(!matching.empty?, "unknown value for #{descr}: #{short_value}", allowed_values)
79
+ multi_choice_assert(matching.length.eql?(1), "ambiguous shortcut for #{descr}: #{short_value}", matching)
80
80
  return enum_to_bool(matching.first) if allowed_values.eql?(BOOLEAN_VALUES)
81
81
  return matching.first
82
82
  end
@@ -84,8 +84,8 @@ module Aspera
84
84
  # Generates error message with list of allowed values
85
85
  # @param error_msg [String] error message
86
86
  # @param choices [Array] list of allowed values
87
- def multi_choice_assert(assertion,error_msg, choices)
88
- raise Cli::BadArgument, [error_msg, 'Use:'].concat(choices.map{|c|"- #{c}"}.sort).join("\n") unless assertion
87
+ def multi_choice_assert(assertion, error_msg, choices)
88
+ raise Cli::BadArgument, [error_msg, 'Use:'].concat(choices.map{|c|"- #{c}"}.sort).join("\n") unless assertion
89
89
  end
90
90
 
91
91
  # change option name with dash to name with underscore
@@ -103,7 +103,7 @@ module Aspera
103
103
  # @param type_list [NilClass, Class, Array[Class]] accepted value type(s)
104
104
  def validate_type(what, descr, value, type_list)
105
105
  return nil if type_list.nil?
106
- assert(type_list.is_a?(Array) && type_list.all?(Class)){'types must be a Class Array'}
106
+ Aspera.assert(type_list.is_a?(Array) && type_list.all?(Class)){'types must be a Class Array'}
107
107
  raise Cli::BadArgument,
108
108
  "#{what.to_s.capitalize} #{descr} is a #{value.class} but must be #{type_list.length > 1 ? 'one of ' : ''}#{type_list.map(&:name).join(',')}" unless \
109
109
  type_list.any?{|t|value.is_a?(t)}
@@ -181,14 +181,15 @@ module Aspera
181
181
  # @param default [Object] default value
182
182
  # @return value, list or nil
183
183
  def get_next_argument(descr, expected: :single, mandatory: true, type: nil, aliases: nil, default: nil)
184
- assert(%i[single multiple].include?(expected) || (expected.is_a?(Array) && expected.all?(Symbol))){'expected must be single, multiple, or array of symbol'}
185
- assert(type.nil? || type.is_a?(Class) || (type.is_a?(Array) && type.all?(Class))){'type must be Class or Array of Class'}
186
- assert(aliases.nil? || (aliases.is_a?(Hash) && aliases.keys.all?(Symbol) && aliases.values.all?(Symbol))){'aliases must be Hash'}
184
+ Aspera.assert(%i[single multiple].include?(expected) || (expected.is_a?(Array) && expected.all?(Symbol))) do
185
+ 'expected must be single, multiple, or array of symbol'
186
+ end
187
+ Aspera.assert(type.nil? || type.is_a?(Class) || (type.is_a?(Array) && type.all?(Class))){'type must be Class or Array of Class'}
188
+ Aspera.assert(aliases.nil? || (aliases.is_a?(Hash) && aliases.keys.all?(Symbol) && aliases.values.all?(Symbol))){'aliases must be Hash'}
187
189
  allowed_types = type
188
190
  unless allowed_types.nil?
189
191
  allowed_types = [allowed_types] unless allowed_types.is_a?(Array)
190
192
  descr = "#{descr} (#{allowed_types.join(', ')})"
191
- Log.log.debug{">>>> #{descr}=#{allowed_types}"}
192
193
  end
193
194
  result =
194
195
  if !@unprocessed_cmd_line_arguments.empty?
@@ -207,7 +208,7 @@ module Aspera
207
208
  allowed_values = [].concat(expected)
208
209
  allowed_values.concat(aliases.keys) unless aliases.nil?
209
210
  self.class.get_from_list(@unprocessed_cmd_line_arguments.shift, descr, allowed_values)
210
- else error_unexpected_value(expected)
211
+ else Aspera.error_unexpected_value(expected)
211
212
  end
212
213
  elsif !default.nil? then default
213
214
  # no value provided, either get value interactively, or exception
@@ -232,7 +233,7 @@ module Aspera
232
233
  # @param mandatory [Boolean] if true, raise error if option not set
233
234
  def get_option(option_symbol, mandatory: false, default: nil)
234
235
  attributes = @declared_options[option_symbol]
235
- assert(attributes){"option not declared: #{option_symbol}"}
236
+ Aspera.assert(attributes){"option not declared: #{option_symbol}"}
236
237
  result = nil
237
238
  case attributes[:read_write]
238
239
  when :accessor
@@ -295,10 +296,10 @@ module Aspera
295
296
  # @param types [Class, Array] accepted value type(s)
296
297
  # @param block [Proc] block to execute when option is found
297
298
  def declare(option_symbol, description, handler: nil, default: nil, values: nil, short: nil, coerce: nil, types: nil, deprecation: nil, &block)
298
- assert(!@declared_options.key?(option_symbol)){"#{option_symbol} already declared"}
299
- assert(description[-1] != '.'){"#{option_symbol} ends with dot"}
300
- assert(description[0] == description[0].upcase){"#{option_symbol} description does not start with capital"}
301
- assert(!['hash', 'extended value'].any?{|s|description.downcase.include?(s) }){"#{option_symbol} shall use :types"}
299
+ Aspera.assert(!@declared_options.key?(option_symbol)){"#{option_symbol} already declared"}
300
+ Aspera.assert(description[-1] != '.'){"#{option_symbol} ends with dot"}
301
+ Aspera.assert(description[0] == description[0].upcase){"#{option_symbol} description does not start with capital"}
302
+ Aspera.assert(!['hash', 'extended value'].any?{|s|description.downcase.include?(s) }){"#{option_symbol} shall use :types"}
302
303
  opt = @declared_options[option_symbol] = {
303
304
  read_write: handler.nil? ? :value : :accessor,
304
305
  # by default passwords and secrets are sensitive, else specify when declaring the option
@@ -306,7 +307,7 @@ module Aspera
306
307
  }
307
308
  if !types.nil?
308
309
  types = [types] unless types.is_a?(Array)
309
- assert(types.all?(Class)){"types must be Array of Class: #{types}"}
310
+ Aspera.assert(types.all?(Class)){"types must be Array of Class: #{types}"}
310
311
  opt[:types] = types
311
312
  description = "#{description} (#{types.map(&:name).join(', ')})"
312
313
  end
@@ -316,8 +317,8 @@ module Aspera
316
317
  end
317
318
  Log.log.debug{"declare: #{option_symbol}: #{opt[:read_write]}".green}
318
319
  if opt[:read_write].eql?(:accessor)
319
- assert_type(handler, Hash)
320
- assert(handler.keys.sort.eql?(%i[m o]))
320
+ Aspera.assert_type(handler, Hash)
321
+ Aspera.assert(handler.keys.sort.eql?(%i[m o]))
321
322
  Log.log.debug{"set attr obj #{option_symbol} (#{handler[:o]},#{handler[:m]})"}
322
323
  opt[:accessor] = AttrAccessor.new(handler[:o], handler[:m], option_symbol)
323
324
  end
@@ -356,11 +357,11 @@ module Aspera
356
357
  set_option(option_symbol, time_string, SOURCE_USER)
357
358
  end
358
359
  when :none
359
- assert(!block.nil?){"missing block for #{option_symbol}"}
360
+ Aspera.assert(!block.nil?){"missing block for #{option_symbol}"}
360
361
  on_args.push(symbol_to_option(option_symbol, nil))
361
362
  on_args.push("-#{short}") if short.is_a?(String)
362
363
  @parser.on(*on_args, &block)
363
- else error_unexpected_value(values)
364
+ else Aspera.error_unexpected_value(values)
364
365
  end
365
366
  Log.log.debug{"on_args=#{on_args}"}
366
367
  end
@@ -368,7 +369,7 @@ module Aspera
368
369
  # Adds each of the keys of specified hash as an option
369
370
  # @param preset_hash [Hash] hash of options to add
370
371
  def add_option_preset(preset_hash, op: :push)
371
- assert_type(preset_hash, Hash)
372
+ Aspera.assert_type(preset_hash, Hash)
372
373
  Log.log.debug{"add_option_preset=#{preset_hash}"}
373
374
  # incremental override
374
375
  preset_hash.each{|k, v|@unprocessed_defaults.send(op, [k.to_sym, v])}
@@ -470,7 +471,7 @@ module Aspera
470
471
  def get_interactive(type, descr, expected: :single)
471
472
  if !@ask_missing_mandatory
472
473
  raise Cli::BadArgument, "missing argument (#{expected}): #{descr}" unless expected.is_a?(Array)
473
- self.class.multi_choice_assert(false,"missing: #{descr}", expected)
474
+ self.class.multi_choice_assert(false, "missing: #{descr}", expected)
474
475
  end
475
476
  result = nil
476
477
  sensitive = type.eql?(:option) && @declared_options[descr.to_sym].is_a?(Hash) && @declared_options[descr.to_sym][:sensitive]