aspera-cli 4.13.0 → 4.15.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 (99) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +81 -7
  4. data/CONTRIBUTING.md +22 -6
  5. data/README.md +2038 -1080
  6. data/bin/ascli +18 -9
  7. data/bin/asession +12 -14
  8. data/examples/dascli +1 -1
  9. data/examples/proxy.pac +1 -1
  10. data/examples/rubyc +24 -0
  11. data/lib/aspera/aoc.rb +219 -159
  12. data/lib/aspera/ascmd.rb +25 -14
  13. data/lib/aspera/cli/basic_auth_plugin.rb +12 -9
  14. data/lib/aspera/cli/error.rb +17 -0
  15. data/lib/aspera/cli/extended_value.rb +47 -12
  16. data/lib/aspera/cli/formatter.rb +260 -179
  17. data/lib/aspera/cli/hints.rb +80 -0
  18. data/lib/aspera/cli/main.rb +104 -156
  19. data/lib/aspera/cli/manager.rb +259 -209
  20. data/lib/aspera/cli/plugin.rb +123 -63
  21. data/lib/aspera/cli/plugins/alee.rb +2 -3
  22. data/lib/aspera/cli/plugins/aoc.rb +341 -261
  23. data/lib/aspera/cli/plugins/ats.rb +22 -21
  24. data/lib/aspera/cli/plugins/bss.rb +5 -5
  25. data/lib/aspera/cli/plugins/config.rb +578 -627
  26. data/lib/aspera/cli/plugins/console.rb +44 -6
  27. data/lib/aspera/cli/plugins/cos.rb +15 -17
  28. data/lib/aspera/cli/plugins/faspex.rb +114 -100
  29. data/lib/aspera/cli/plugins/faspex5.rb +411 -264
  30. data/lib/aspera/cli/plugins/node.rb +354 -259
  31. data/lib/aspera/cli/plugins/orchestrator.rb +61 -29
  32. data/lib/aspera/cli/plugins/preview.rb +82 -90
  33. data/lib/aspera/cli/plugins/server.rb +79 -32
  34. data/lib/aspera/cli/plugins/shares.rb +55 -42
  35. data/lib/aspera/cli/sync_actions.rb +68 -0
  36. data/lib/aspera/cli/transfer_agent.rb +66 -73
  37. data/lib/aspera/cli/transfer_progress.rb +74 -0
  38. data/lib/aspera/cli/version.rb +1 -1
  39. data/lib/aspera/colors.rb +12 -8
  40. data/lib/aspera/command_line_builder.rb +14 -11
  41. data/lib/aspera/cos_node.rb +3 -2
  42. data/lib/aspera/data/6 +0 -0
  43. data/lib/aspera/environment.rb +24 -9
  44. data/lib/aspera/fasp/agent_aspera.rb +126 -0
  45. data/lib/aspera/fasp/agent_base.rb +31 -77
  46. data/lib/aspera/fasp/agent_connect.rb +25 -21
  47. data/lib/aspera/fasp/agent_direct.rb +89 -103
  48. data/lib/aspera/fasp/agent_httpgw.rb +231 -149
  49. data/lib/aspera/fasp/agent_node.rb +41 -34
  50. data/lib/aspera/fasp/agent_trsdk.rb +75 -32
  51. data/lib/aspera/fasp/error_info.rb +4 -2
  52. data/lib/aspera/fasp/faux_file.rb +52 -0
  53. data/lib/aspera/fasp/installation.rb +53 -195
  54. data/lib/aspera/fasp/management.rb +244 -0
  55. data/lib/aspera/fasp/parameters.rb +71 -37
  56. data/lib/aspera/fasp/parameters.yaml +76 -8
  57. data/lib/aspera/fasp/products.rb +162 -0
  58. data/lib/aspera/fasp/resume_policy.rb +3 -3
  59. data/lib/aspera/fasp/transfer_spec.rb +7 -6
  60. data/lib/aspera/fasp/uri.rb +26 -24
  61. data/lib/aspera/faspex_gw.rb +2 -2
  62. data/lib/aspera/faspex_postproc.rb +2 -2
  63. data/lib/aspera/hash_ext.rb +14 -4
  64. data/lib/aspera/json_rpc.rb +49 -0
  65. data/lib/aspera/keychain/macos_security.rb +13 -13
  66. data/lib/aspera/line_logger.rb +23 -0
  67. data/lib/aspera/log.rb +58 -16
  68. data/lib/aspera/node.rb +157 -92
  69. data/lib/aspera/oauth.rb +37 -19
  70. data/lib/aspera/open_application.rb +4 -4
  71. data/lib/aspera/persistency_action_once.rb +1 -1
  72. data/lib/aspera/persistency_folder.rb +2 -2
  73. data/lib/aspera/preview/file_types.rb +4 -2
  74. data/lib/aspera/preview/generator.rb +22 -35
  75. data/lib/aspera/preview/options.rb +2 -0
  76. data/lib/aspera/preview/terminal.rb +73 -16
  77. data/lib/aspera/preview/utils.rb +21 -28
  78. data/lib/aspera/proxy_auto_config.js +2 -2
  79. data/lib/aspera/rest.rb +136 -68
  80. data/lib/aspera/rest_call_error.rb +1 -1
  81. data/lib/aspera/rest_error_analyzer.rb +15 -14
  82. data/lib/aspera/rest_errors_aspera.rb +37 -34
  83. data/lib/aspera/secret_hider.rb +18 -15
  84. data/lib/aspera/ssh.rb +5 -2
  85. data/lib/aspera/sync.rb +127 -119
  86. data/lib/aspera/temp_file_manager.rb +10 -3
  87. data/lib/aspera/web_auth.rb +10 -7
  88. data/lib/aspera/web_server_simple.rb +9 -4
  89. data.tar.gz.sig +0 -0
  90. metadata +34 -17
  91. metadata.gz.sig +0 -0
  92. data/docs/test_env.conf +0 -186
  93. data/lib/aspera/cli/listener/line_dump.rb +0 -19
  94. data/lib/aspera/cli/listener/logger.rb +0 -22
  95. data/lib/aspera/cli/listener/progress.rb +0 -50
  96. data/lib/aspera/cli/listener/progress_multi.rb +0 -84
  97. data/lib/aspera/cli/plugins/sync.rb +0 -44
  98. data/lib/aspera/data/7 +0 -0
  99. data/lib/aspera/fasp/listener.rb +0 -13
@@ -7,32 +7,17 @@ require 'aspera/cli/extended_value'
7
7
  require 'aspera/cli/transfer_agent'
8
8
  require 'aspera/cli/version'
9
9
  require 'aspera/cli/info'
10
- require 'aspera/fasp/error'
11
- require 'aspera/open_application'
12
- require 'aspera/temp_file_manager'
13
- require 'aspera/persistency_folder'
14
- require 'aspera/log'
15
- require 'aspera/rest'
16
- require 'aspera/nagios'
17
- require 'aspera/colors'
10
+ require 'aspera/cli/hints'
18
11
  require 'aspera/secret_hider'
19
- require 'net/ssh'
12
+ require 'aspera/log'
20
13
 
21
14
  module Aspera
22
15
  module Cli
23
16
  # The main CLI class
24
17
  class Main
25
- # prefix to display error messages in user messages (terminal)
26
- ERROR_FLASH = 'ERROR:'.bg_red.gray.blink.freeze
27
- WARNING_FLASH = 'WARNING:'.bg_red.gray.blink.freeze
28
- private_constant :ERROR_FLASH, :WARNING_FLASH
29
-
30
- # store transfer result using this key and use result_transfer_multiple
18
+ # Plugins store transfer result using this key and use result_transfer_multiple()
31
19
  STATUS_FIELD = 'status'
32
20
 
33
- # for testing only
34
- SELF_SIGNED_CERT = OpenSSL::SSL.const_get(:enon_yfirev.to_s.upcase.reverse)
35
-
36
21
  class << self
37
22
  # expect some list, but nothing to display
38
23
  def result_empty; return {type: :empty, data: :nil}; end
@@ -68,85 +53,55 @@ module Aspera
68
53
  raise global_status unless global_status.eql?(:success)
69
54
  return {type: :object_list, data: status_table}
70
55
  end
71
- end
56
+ end # self
72
57
 
73
58
  private
74
59
 
60
+ # shortcuts helpers like in plugins
61
+ %i[options transfer config formatter persistency].each do |name|
62
+ define_method(name){@agents[name]}
63
+ end
64
+
75
65
  # =============================================================
76
66
  # Parameter handlers
77
67
  #
78
- attr_accessor :option_insecure, :option_http_options, :option_cache_tokens
79
-
80
- def option_ui; OpenApplication.instance.url_method; end
81
-
82
- def option_ui=(value); OpenApplication.instance.url_method = value; end
83
-
84
- # called every time a new REST HTTP session is opened
85
- # @param http [Net::HTTP] the newly created http session object
86
- def http_parameters=(http)
87
- if @option_insecure
88
- url = http.inspect.gsub(/^[^ ]* /, 'https://').gsub(/ [^ ]*$/, '')
89
- if !@ssl_warned_urls.include?(url)
90
- @formatter.display_message(:error, "#{WARNING_FLASH} ignoring certificate for: #{url}. Do not use unsafe certificates in production.")
91
- @ssl_warned_urls.push(url)
92
- end
93
- http.verify_mode = SELF_SIGNED_CERT
94
- end
95
- http.set_debug_output($stdout) if @option_rest_debug
96
- raise 'http_options expects Hash' unless @option_http_options.is_a?(Hash)
97
-
98
- @option_http_options.each do |k, v|
99
- method = "#{k}=".to_sym
100
- # check if accessor is a method of Net::HTTP
101
- # continue_timeout= read_timeout= write_timeout=
102
- if http.respond_to?(method)
103
- http.send(method, v)
104
- else
105
- Log.log.error{"no such attribute: #{k}"}
106
- end
107
- end
108
- end
109
68
 
110
- # minimum initialization
69
+ # minimum initialization, no exception raised
111
70
  def initialize(argv)
112
- # first thing : manage debug level (allows debugging of option parser)
113
- early_debug_setup(argv)
114
- # compare $0 with expected name
115
- current_prog_name = File.basename($PROGRAM_NAME)
116
- @formatter.display_message(:error, "#{'WARNING'.bg_red.blink.gray} Please use '#{PROGRAM_NAME}' instead of '#{current_prog_name}'") \
117
- unless current_prog_name.eql?(PROGRAM_NAME)
71
+ @argv = argv
72
+ # environment provided to plugin for various capabilities
73
+ @agents = {}
118
74
  @option_help = false
119
- @bash_completion = false
120
75
  @option_show_config = false
121
- @option_insecure = false
122
- @option_rest_debug = false
123
- @option_cache_tokens = true
124
- @option_http_options = {}
125
- @ssl_warned_urls = []
126
- # environment provided to plugin for various capabilities
127
- @plugin_env = {}
76
+ @bash_completion = false
77
+ end
78
+
79
+ # This can throw exception if there is a problem with the environment, needs to be caught by execute method
80
+ def init_agents_and_options
81
+ # first thing : manage debug level (allows debugging of option parser)
82
+ early_debug_setup
83
+ @agents[:formatter] = Formatter.new
84
+ @agents[:options] = Manager.new(PROGRAM_NAME)
128
85
  # give command line arguments to option manager
129
- @plugin_env[:options] = @opt_mgr = Manager.new(PROGRAM_NAME, argv: argv)
86
+ options.parse_command_line(@argv)
130
87
  # formatter adds options
131
- @formatter = @plugin_env[:formatter] = Formatter.new(@plugin_env[:options])
132
- Rest.user_agent = PROGRAM_NAME
133
- Rest.session_cb = lambda{|http|self.http_parameters = http}
88
+ formatter.declare_options(options)
89
+ # compare $0 with expected name
90
+ current_prog_name = File.basename($PROGRAM_NAME)
91
+ formatter.display_message(
92
+ :error,
93
+ "#{Formatter::WARNING_FLASH} Please use '#{PROGRAM_NAME}' instead of '#{current_prog_name}'") unless current_prog_name.eql?(PROGRAM_NAME)
134
94
  # declare and parse global options
135
- init_global_options
95
+ declare_global_options
136
96
  # the Config plugin adds the @preset parser, so declare before TransferAgent which may use it
137
- @plugin_env[:config] = Plugins::Config.new(@plugin_env, gem: GEM_NAME, name: PROGRAM_NAME, help: DOC_URL, version: Aspera::Cli::VERSION)
138
- # the TransferAgent plugin may use the @preset parser
139
- @plugin_env[:transfer] = TransferAgent.new(@plugin_env[:options], @plugin_env[:config])
97
+ @agents[:config] = Plugins::Config.new(@agents, gem: GEM_NAME, name: PROGRAM_NAME, help: DOC_URL, version: Aspera::Cli::VERSION)
140
98
  # data persistency
141
- @plugin_env[:persistency] = PersistencyFolder.new(File.join(@plugin_env[:config].main_folder, 'persist_store'))
99
+ raise 'internal error: missing persistency object' unless @agents[:persistency]
100
+ # the TransferAgent plugin may use the @preset parser
101
+ @agents[:transfer] = TransferAgent.new(options, config)
142
102
  Log.log.debug('plugin env created'.red)
143
- Oauth.persist_mgr = @plugin_env[:persistency] if @option_cache_tokens
144
- Fasp::Parameters.file_list_folder = File.join(@plugin_env[:config].main_folder, 'filelists')
145
- Aspera::RestErrorAnalyzer.instance.log_file = File.join(@plugin_env[:config].main_folder, 'rest_exceptions.log')
146
- # register aspera REST call error handlers
147
- Aspera::RestErrorsAspera.register_handlers
148
103
  # set banner when all environment is created so that additional extended value modifiers are known, e.g. @preset
149
- @opt_mgr.parser.banner = app_banner
104
+ options.parser.banner = app_banner
150
105
  end
151
106
 
152
107
  def app_banner
@@ -166,7 +121,6 @@ module Aspera
166
121
  #{t}source repo: #{SRC_URL}
167
122
 
168
123
  ENVIRONMENT VARIABLES
169
- #{t}#{@plugin_env[:config].conf_dir_env_var} config folder, default: $HOME/#{Plugins::Config::ASPERA_HOME_FOLDER_NAME}/#{PROGRAM_NAME}
170
124
  #{t}Any option can be set as an environment variable, refer to the manual
171
125
 
172
126
  COMMANDS
@@ -185,44 +139,36 @@ module Aspera
185
139
  end
186
140
 
187
141
  # define header for manual
188
- def init_global_options
189
- Log.log.debug('init_global_options')
190
- @opt_mgr.add_opt_switch(:help, '-h', 'Show this message.') { @option_help = true }
191
- @opt_mgr.add_opt_switch(:bash_comp, 'generate bash completion for command') { @bash_completion = true }
192
- @opt_mgr.add_opt_switch(:show_config, 'Display parameters used for the provided action.') { @option_show_config = true }
193
- @opt_mgr.add_opt_switch(:rest_debug, '-r', 'more debug for HTTP calls') { @option_rest_debug = true }
194
- @opt_mgr.add_opt_switch(:version, '-v', 'display version') { @formatter.display_message(:data, Aspera::Cli::VERSION); Process.exit(0) } # rubocop:disable Style/Semicolon, Layout/LineLength
195
- @opt_mgr.add_opt_switch(:warnings, '-w', 'check for language warnings') { $VERBOSE = true }
196
- # handler must be set before declaration
197
- @opt_mgr.set_obj_attr(:log_level, Log.instance, :level)
198
- @opt_mgr.set_obj_attr(:logger, Log.instance, :logger_type)
199
- @opt_mgr.set_obj_attr(:insecure, self, :option_insecure, :no)
200
- @opt_mgr.set_obj_attr(:ui, self, :option_ui)
201
- @opt_mgr.set_obj_attr(:http_options, self, :option_http_options)
202
- @opt_mgr.set_obj_attr(:log_secrets, SecretHider, :log_secrets)
203
- @opt_mgr.set_obj_attr(:cache_tokens, self, :option_cache_tokens)
204
- @opt_mgr.add_opt_list(:ui, OpenApplication.user_interfaces, 'method to start browser')
205
- @opt_mgr.add_opt_list(:log_level, Log.levels, 'Log level')
206
- @opt_mgr.add_opt_list(:logger, Log::LOG_TYPES, 'logging method')
207
- @opt_mgr.add_opt_simple(:lock_port, 'prevent dual execution of a command, e.g. in cron')
208
- @opt_mgr.add_opt_simple(:http_options, 'options for http socket (extended value)')
209
- @opt_mgr.add_opt_boolean(:insecure, 'do not validate HTTPS certificate')
210
- @opt_mgr.add_opt_boolean(:once_only, 'process only new items (some commands)')
211
- @opt_mgr.add_opt_boolean(:log_secrets, 'show passwords in logs')
212
- @opt_mgr.add_opt_boolean(:cache_tokens, 'save and reuse Oauth tokens')
213
- @opt_mgr.set_option(:ui, OpenApplication.default_gui_mode)
214
- @opt_mgr.set_option(:once_only, false)
142
+ def declare_global_options
143
+ Log.log.debug('declare_global_options')
144
+ options.declare(:help, 'Show this message', values: :none, short: 'h') { @option_help = true }
145
+ options.declare(:bash_comp, 'Generate bash completion for command', values: :none) { @bash_completion = true }
146
+ options.declare(:show_config, 'Display parameters used for the provided action', values: :none) { @option_show_config = true }
147
+ 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
148
+ options.declare(:warnings, 'Check for language warnings', values: :none, short: 'w') { $VERBOSE = true }
149
+ options.declare(
150
+ :ui, 'Method to start browser',
151
+ values: OpenApplication.user_interfaces,
152
+ handler: {o: OpenApplication.instance, m: :url_method},
153
+ default: OpenApplication.default_gui_mode)
154
+ options.declare(:log_level, 'Log level', values: Log.levels, handler: {o: Log.instance, m: :level})
155
+ options.declare(:logger, 'Logging method', values: Log::LOG_TYPES, handler: {o: Log.instance, m: :logger_type})
156
+ options.declare(:lock_port, 'Prevent dual execution of a command, e.g. in cron', coerce: Integer, types: Integer)
157
+ options.declare(:once_only, 'Process only new items (some commands)', values: :bool, default: false)
158
+ options.declare(:log_secrets, 'Show passwords in logs', values: :bool, handler: {o: SecretHider, m: :log_secrets})
159
+ options.declare(:clean_temp, 'Cleanup temporary files on exit', values: :bool, handler: {o: TempFileManager.instance, m: :cleanup_on_exit})
160
+ options.declare(:pid_file, 'Write process identifier to file, delete on exit', types: String)
215
161
  # parse declared options
216
- @opt_mgr.parse_options!
162
+ options.parse_options!
217
163
  end
218
164
 
219
165
  # @return the plugin instance, based on name
220
166
  # also loads the plugin options, and default values from conf file
221
167
  # @param plugin_name_sym : symbol for plugin name
222
168
  def get_plugin_instance_with_options(plugin_name_sym, env=nil)
223
- env ||= @plugin_env
169
+ env ||= @agents
224
170
  Log.log.debug{"get_plugin_instance_with_options(#{plugin_name_sym})"}
225
- require @plugin_env[:config].plugins[plugin_name_sym][:require_stanza]
171
+ require config.plugins[plugin_name_sym][:require_stanza]
226
172
  # load default params only if no param already loaded before plugin instantiation
227
173
  env[:config].add_plugin_default_preset(plugin_name_sym)
228
174
  command_plugin = Plugins::Config.plugin_class(plugin_name_sym).new(env)
@@ -232,8 +178,8 @@ module Aspera
232
178
  end
233
179
 
234
180
  def generate_bash_completion
235
- if @opt_mgr.get_next_argument('', expected: :multiple, mandatory: false).nil?
236
- @plugin_env[:config].plugins.each_key{|p|puts p.to_s}
181
+ if options.get_next_argument('', expected: :multiple, mandatory: false).nil?
182
+ config.plugins.each_key{|p|puts p.to_s}
237
183
  else
238
184
  Log.log.warn('only first level completion so far')
239
185
  end
@@ -243,19 +189,19 @@ module Aspera
243
189
  def exit_with_usage(all_plugins)
244
190
  Log.log.debug('exit_with_usage'.bg_red)
245
191
  # display main plugin options
246
- @formatter.display_message(:error, @opt_mgr.parser)
192
+ formatter.display_message(:error, options.parser)
247
193
  if all_plugins
248
194
  # list plugins that have a "require" field, i.e. all but main plugin
249
- @plugin_env[:config].plugins.each_key do |plugin_name_sym|
195
+ config.plugins.each_key do |plugin_name_sym|
250
196
  next if plugin_name_sym.eql?(Plugins::Config::CONF_PLUGIN_SYM)
251
197
  # override main option parser with a brand new, to avoid having global options
252
- plugin_env = @plugin_env.clone
253
- plugin_env[:man_only] = true
198
+ plugin_env = @agents.clone
199
+ plugin_env[:all_manuals] = true # force declaration of all options
254
200
  plugin_env[:options] = Manager.new(PROGRAM_NAME)
255
201
  plugin_env[:options].parser.banner = '' # remove default banner
256
202
  get_plugin_instance_with_options(plugin_name_sym, plugin_env)
257
203
  # display generated help for plugin options
258
- @formatter.display_message(:error, plugin_env[:options].parser.help)
204
+ formatter.display_message(:error, plugin_env[:options].parser.help)
259
205
  end
260
206
  end
261
207
  Process.exit(0)
@@ -265,9 +211,9 @@ module Aspera
265
211
 
266
212
  # early debug for parser
267
213
  # Note: does not accept shortcuts
268
- def early_debug_setup(argv)
214
+ def early_debug_setup
269
215
  Aspera::Log.instance.program_name = PROGRAM_NAME
270
- argv.each do |arg|
216
+ @argv.each do |arg|
271
217
  case arg
272
218
  when '--' then break
273
219
  when /^--log-level=(.*)/ then Aspera::Log.instance.level = Regexp.last_match(1).to_sym
@@ -280,69 +226,78 @@ module Aspera
280
226
 
281
227
  # this is the main function called by initial script just after constructor
282
228
  def process_command_line
283
- Log.log.debug('process_command_line')
284
229
  # catch exception information , if any
285
230
  exception_info = nil
286
- # false if command shall not be executed ("once_only")
231
+ # false if command shall not be executed (e.g. --show-config)
287
232
  execute_command = true
233
+ # catch exceptions
288
234
  begin
235
+ init_agents_and_options
289
236
  # find plugins, shall be after parse! ?
290
- @plugin_env[:config].add_plugins_from_lookup_folders
237
+ config.add_plugins_from_lookup_folders
291
238
  # help requested without command ? (plugins must be known here)
292
- exit_with_usage(true) if @option_help && @opt_mgr.command_or_arg_empty?
239
+ exit_with_usage(true) if @option_help && options.command_or_arg_empty?
293
240
  generate_bash_completion if @bash_completion
294
- @plugin_env[:config].periodic_check_newer_gem_version
241
+ config.periodic_check_newer_gem_version
295
242
  command_sym =
296
- if @option_show_config && @opt_mgr.command_or_arg_empty?
243
+ if @option_show_config && options.command_or_arg_empty?
297
244
  Plugins::Config::CONF_PLUGIN_SYM
298
245
  else
299
- @opt_mgr.get_next_command(@plugin_env[:config].plugins.keys.dup.unshift(:help))
246
+ options.get_next_command(config.plugins.keys.dup.unshift(:help))
300
247
  end
301
248
  # command will not be executed, but we need manual
302
- @opt_mgr.fail_on_missing_mandatory = false if @option_help || @option_show_config
249
+ options.fail_on_missing_mandatory = false if @option_help || @option_show_config
303
250
  # main plugin is not dynamically instantiated
304
251
  case command_sym
305
252
  when :help
306
253
  exit_with_usage(true)
307
254
  when Plugins::Config::CONF_PLUGIN_SYM
308
- command_plugin = @plugin_env[:config]
255
+ command_plugin = config
309
256
  else
310
257
  # get plugin, set options, etc
311
258
  command_plugin = get_plugin_instance_with_options(command_sym)
312
259
  # parse plugin specific options
313
- @opt_mgr.parse_options!
260
+ options.parse_options!
314
261
  end
315
262
  # help requested for current plugin
316
263
  exit_with_usage(false) if @option_help
317
264
  if @option_show_config
318
- @formatter.display_results({type: :single_object, data: @opt_mgr.declared_options(only_defined: true)})
265
+ formatter.display_results({type: :single_object, data: options.known_options(only_defined: true).stringify_keys})
319
266
  execute_command = false
320
267
  end
321
268
  # locking for single execution (only after "per plugin" option, in case lock port is there)
322
- lock_port = @opt_mgr.get_option(:lock_port)
269
+ lock_port = options.get_option(:lock_port)
323
270
  if !lock_port.nil?
324
271
  begin
325
272
  # no need to close later, will be freed on process exit. must save in member else it is garbage collected
326
- Log.log.debug{"Opening lock port #{lock_port.to_i}"}
327
- @tcp_server = TCPServer.new('127.0.0.1', lock_port.to_i)
273
+ Log.log.debug{"Opening lock port #{lock_port}"}
274
+ @tcp_server = TCPServer.new('127.0.0.1', lock_port)
328
275
  rescue StandardError => e
329
276
  execute_command = false
330
277
  Log.log.warn{"Another instance is already running (#{e.message})."}
331
278
  end
332
279
  end
280
+ pid_file = options.get_option(:pid_file)
281
+ if !pid_file.nil?
282
+ File.write(pid_file, Process.pid)
283
+ Log.log.debug{"Wrote pid #{Process.pid} to #{pid_file}"}
284
+ at_exit{File.delete(pid_file)}
285
+ end
333
286
  # execute and display (if not exclusive execution)
334
- @formatter.display_results(command_plugin.execute_action) if execute_command
287
+ formatter.display_results(command_plugin.execute_action) if execute_command
288
+ # save config file if command modified it
289
+ config.save_config_file_if_needed
335
290
  # finish
336
- @plugin_env[:transfer].shutdown
291
+ transfer.shutdown
337
292
  rescue Net::SSH::AuthenticationFailed => e; exception_info = {e: e, t: 'SSH', security: true}
338
293
  rescue OpenSSL::SSL::SSLError => e; exception_info = {e: e, t: 'SSL'}
339
- rescue CliBadArgument => e; exception_info = {e: e, t: 'Argument', usage: true}
340
- rescue CliNoSuchId => e; exception_info = {e: e, t: 'Identifier'}
341
- rescue CliError => e; exception_info = {e: e, t: 'Tool', usage: true}
342
- rescue Fasp::Error => e; exception_info = {e: e, t: 'FASP(ascp)'}
294
+ rescue Cli::BadArgument => e; exception_info = {e: e, t: 'Argument', usage: true}
295
+ rescue Cli::NoSuchIdentifier => e; exception_info = {e: e, t: 'Identifier'}
296
+ rescue Cli::Error => e; exception_info = {e: e, t: 'Tool', usage: true}
297
+ rescue Fasp::Error => e; exception_info = {e: e, t: 'Transfer'}
343
298
  rescue Aspera::RestCallError => e; exception_info = {e: e, t: 'Rest'}
344
299
  rescue SocketError => e; exception_info = {e: e, t: 'Network'}
345
- rescue StandardError => e; exception_info = {e: e, t: 'Other', debug: true}
300
+ rescue StandardError => e; exception_info = {e: e, t: "Other(#{e.class.name})", debug: true}
346
301
  rescue Interrupt => e; exception_info = {e: e, t: 'Interruption', debug: true}
347
302
  end
348
303
  # cleanup file list files
@@ -350,22 +305,15 @@ module Aspera
350
305
  # 1- processing of error condition
351
306
  unless exception_info.nil?
352
307
  Log.log.warn(exception_info[:e].message) if Aspera::Log.instance.logger_type.eql?(:syslog) && exception_info[:security]
353
- @formatter.display_message(:error, "#{ERROR_FLASH} #{exception_info[:t]}: #{exception_info[:e].message}")
354
- @formatter.display_message(:error, 'Use option -h to get help.') if exception_info[:usage]
355
- # Provide hint on FASP errors
356
- if exception_info[:e].is_a?(Fasp::Error) && exception_info[:e].message.eql?('Remote host is not who we expected')
357
- @formatter.display_message(:error, "For this specific error, refer to:\n"\
358
- "#{SRC_URL}#error-remote-host-is-not-who-we-expected\nAdd this to arguments:\n--ts=@json:'{\"sshfp\":null}'")
359
- end
360
- # Provide hint on SSL errors
361
- if exception_info[:e].is_a?(OpenSSL::SSL::SSLError) && ['does not match the server certificate'].any?{|m|exception_info[:e].message.include?(m)}
362
- @formatter.display_message(:error, "You can ignore SSL errors with option:\n--insecure=yes")
363
- end
308
+ formatter.display_message(:error, "#{Formatter::ERROR_FLASH} #{exception_info[:t]}: #{exception_info[:e].message}")
309
+ formatter.display_message(:error, 'Use option -h to get help.') if exception_info[:usage]
310
+ # Is that a known error condition with proposal for remediation ?
311
+ Hints.hint_for(exception_info[:e], formatter)
364
312
  end
365
313
  # 2- processing of command not processed (due to exception or bad command line)
366
314
  if execute_command || @option_show_config
367
- @opt_mgr.final_errors.each do |msg|
368
- @formatter.display_message(:error, "#{ERROR_FLASH} Argument: #{msg}")
315
+ options.final_errors.each do |msg|
316
+ formatter.display_message(:error, "#{Formatter::ERROR_FLASH} Argument: #{msg}")
369
317
  # add code as exception if there is not already an error
370
318
  exception_info = {e: Exception.new(msg), t: 'UnusedArg'} if exception_info.nil?
371
319
  end
@@ -373,9 +321,9 @@ module Aspera
373
321
  # 3- in case of error, fail the process status
374
322
  unless exception_info.nil?
375
323
  # show stack trace in debug mode
376
- raise exception_info[:e] if Log.instance.level.eql?(:debug)
324
+ raise exception_info[:e] if Log.log.debug?
377
325
  # else give hint and exit
378
- @formatter.display_message(:error, 'Use --log-level=debug to get more details.') if exception_info[:debug]
326
+ formatter.display_message(:error, 'Use --log-level=debug to get more details.') if exception_info[:debug]
379
327
  Process.exit(1)
380
328
  end
381
329
  return nil