aspera-cli 4.4.0 → 4.7.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. data/README.md +2095 -1503
  3. data/bin/ascli +2 -1
  4. data/bin/asession +4 -5
  5. data/docs/test_env.conf +3 -0
  6. data/examples/aoc.rb +4 -3
  7. data/examples/faspex4.rb +25 -25
  8. data/examples/proxy.pac +1 -1
  9. data/examples/transfer.rb +17 -17
  10. data/lib/aspera/aoc.rb +238 -185
  11. data/lib/aspera/ascmd.rb +93 -83
  12. data/lib/aspera/ats_api.rb +11 -10
  13. data/lib/aspera/cli/basic_auth_plugin.rb +13 -14
  14. data/lib/aspera/cli/extended_value.rb +42 -33
  15. data/lib/aspera/cli/formater.rb +142 -108
  16. data/lib/aspera/cli/info.rb +17 -0
  17. data/lib/aspera/cli/listener/line_dump.rb +3 -2
  18. data/lib/aspera/cli/listener/logger.rb +2 -1
  19. data/lib/aspera/cli/listener/progress.rb +16 -18
  20. data/lib/aspera/cli/listener/progress_multi.rb +18 -21
  21. data/lib/aspera/cli/main.rb +173 -149
  22. data/lib/aspera/cli/manager.rb +163 -168
  23. data/lib/aspera/cli/plugin.rb +43 -31
  24. data/lib/aspera/cli/plugins/alee.rb +6 -6
  25. data/lib/aspera/cli/plugins/aoc.rb +405 -370
  26. data/lib/aspera/cli/plugins/ats.rb +86 -79
  27. data/lib/aspera/cli/plugins/bss.rb +14 -16
  28. data/lib/aspera/cli/plugins/config.rb +580 -362
  29. data/lib/aspera/cli/plugins/console.rb +23 -19
  30. data/lib/aspera/cli/plugins/cos.rb +18 -18
  31. data/lib/aspera/cli/plugins/faspex.rb +201 -158
  32. data/lib/aspera/cli/plugins/faspex5.rb +80 -57
  33. data/lib/aspera/cli/plugins/node.rb +183 -166
  34. data/lib/aspera/cli/plugins/orchestrator.rb +71 -67
  35. data/lib/aspera/cli/plugins/preview.rb +92 -96
  36. data/lib/aspera/cli/plugins/server.rb +79 -75
  37. data/lib/aspera/cli/plugins/shares.rb +35 -19
  38. data/lib/aspera/cli/plugins/sync.rb +20 -22
  39. data/lib/aspera/cli/transfer_agent.rb +76 -113
  40. data/lib/aspera/cli/version.rb +2 -1
  41. data/lib/aspera/colors.rb +35 -27
  42. data/lib/aspera/command_line_builder.rb +48 -34
  43. data/lib/aspera/cos_node.rb +29 -21
  44. data/lib/aspera/data_repository.rb +3 -2
  45. data/lib/aspera/environment.rb +50 -45
  46. data/lib/aspera/fasp/{manager.rb → agent_base.rb} +28 -25
  47. data/lib/aspera/fasp/{connect.rb → agent_connect.rb} +52 -43
  48. data/lib/aspera/fasp/{local.rb → agent_direct.rb} +58 -72
  49. data/lib/aspera/fasp/{http_gw.rb → agent_httpgw.rb} +37 -43
  50. data/lib/aspera/fasp/{node.rb → agent_node.rb} +35 -16
  51. data/lib/aspera/fasp/agent_trsdk.rb +104 -0
  52. data/lib/aspera/fasp/error.rb +2 -1
  53. data/lib/aspera/fasp/error_info.rb +68 -52
  54. data/lib/aspera/fasp/installation.rb +152 -124
  55. data/lib/aspera/fasp/listener.rb +1 -0
  56. data/lib/aspera/fasp/parameters.rb +87 -92
  57. data/lib/aspera/fasp/parameters.yaml +305 -249
  58. data/lib/aspera/fasp/resume_policy.rb +11 -14
  59. data/lib/aspera/fasp/transfer_spec.rb +26 -0
  60. data/lib/aspera/fasp/uri.rb +22 -21
  61. data/lib/aspera/faspex_gw.rb +55 -89
  62. data/lib/aspera/hash_ext.rb +4 -3
  63. data/lib/aspera/id_generator.rb +8 -7
  64. data/lib/aspera/keychain/encrypted_hash.rb +121 -0
  65. data/lib/aspera/keychain/macos_security.rb +90 -0
  66. data/lib/aspera/log.rb +55 -37
  67. data/lib/aspera/nagios.rb +13 -12
  68. data/lib/aspera/node.rb +30 -25
  69. data/lib/aspera/oauth.rb +175 -226
  70. data/lib/aspera/open_application.rb +4 -3
  71. data/lib/aspera/persistency_action_once.rb +6 -6
  72. data/lib/aspera/persistency_folder.rb +5 -9
  73. data/lib/aspera/preview/file_types.rb +6 -5
  74. data/lib/aspera/preview/generator.rb +25 -24
  75. data/lib/aspera/preview/options.rb +16 -14
  76. data/lib/aspera/preview/utils.rb +98 -98
  77. data/lib/aspera/{proxy_auto_config.erb.js → proxy_auto_config.js} +23 -31
  78. data/lib/aspera/proxy_auto_config.rb +111 -20
  79. data/lib/aspera/rest.rb +154 -135
  80. data/lib/aspera/rest_call_error.rb +2 -2
  81. data/lib/aspera/rest_error_analyzer.rb +23 -25
  82. data/lib/aspera/rest_errors_aspera.rb +15 -14
  83. data/lib/aspera/ssh.rb +12 -10
  84. data/lib/aspera/sync.rb +42 -41
  85. data/lib/aspera/temp_file_manager.rb +18 -14
  86. data/lib/aspera/timer_limiter.rb +2 -1
  87. data/lib/aspera/uri_reader.rb +7 -5
  88. data/lib/aspera/web_auth.rb +79 -76
  89. metadata +116 -29
  90. data/docs/Makefile +0 -66
  91. data/docs/README.erb.md +0 -3973
  92. data/docs/README.md +0 -13
  93. data/docs/diagrams.txt +0 -49
  94. data/docs/doc_tools.rb +0 -58
  95. data/lib/aspera/api_detector.rb +0 -60
  96. data/lib/aspera/cli/plugins/shares2.rb +0 -114
  97. data/lib/aspera/secrets.rb +0 -20
@@ -1,119 +1,179 @@
1
+ # frozen_string_literal: true
1
2
  require 'aspera/cli/manager'
2
3
  require 'aspera/cli/formater'
3
4
  require 'aspera/cli/plugins/config'
4
5
  require 'aspera/cli/extended_value'
5
6
  require 'aspera/cli/transfer_agent'
6
7
  require 'aspera/cli/version'
8
+ require 'aspera/cli/info'
9
+ require 'aspera/fasp/error'
7
10
  require 'aspera/open_application'
8
11
  require 'aspera/temp_file_manager'
9
12
  require 'aspera/persistency_folder'
10
13
  require 'aspera/log'
11
14
  require 'aspera/rest'
12
15
  require 'aspera/nagios'
13
- require 'aspera/secrets'
16
+ require 'aspera/colors'
14
17
 
15
18
  module Aspera
16
19
  module Cli
17
20
  # The main CLI class
18
21
  class Main
22
+ # prefix to display error messages
23
+ ERROR_FLASH='ERROR:'.bg_red.gray.blink.freeze
24
+ private_constant :ERROR_FLASH
19
25
 
20
- attr_reader :plugin_env
21
- private
22
- # name of application, also foldername where config is stored
23
- PROGRAM_NAME = 'ascli'
24
- # name of the containing gem, same as in <gem name>.gemspec
25
- GEM_NAME = 'aspera-cli'
26
- HELP_URL = "http://www.rubydoc.info/gems/#{GEM_NAME}"
27
- GEM_URL = "https://rubygems.org/gems/#{GEM_NAME}"
28
- SRC_URL = "https://github.com/IBM/aspera-cli"
26
+ # store transfer result using this key and use result_transfer_multiple
29
27
  STATUS_FIELD = 'status'
30
28
 
31
- private_constant :PROGRAM_NAME,:GEM_NAME,:HELP_URL,:GEM_URL
29
+ class << self
30
+ # expect some list, but nothing to display
31
+ def result_empty; return {type: :empty, data: :nil}; end
32
+
33
+ # nothing expected
34
+ def result_nothing; return {type: :nothing, data: :nil}; end
35
+
36
+ def result_status(status); return {type: :status, data: status}; end
37
+
38
+ def result_success; return result_status('complete'); end
39
+
40
+ # Process statuses of finished transfer sessions
41
+ # raise exception if there is one error
42
+ # else returns an empty status
43
+ def result_transfer(statuses)
44
+ worst=TransferAgent.session_status(statuses)
45
+ raise worst unless worst.eql?(:success)
46
+ return Main.result_nothing
47
+ end
48
+
49
+ # used when one command executes several transfer jobs (each job being possibly multi session)
50
+ # @param status_table [Array] [{STATUS_FIELD=>[status array],...},...]
51
+ # @return a status object suitable as command result
52
+ # each element has a key STATUS_FIELD which contains the result of possibly multiple sessions
53
+ def result_transfer_multiple(status_table)
54
+ global_status=:success
55
+ # transform status array into string and find if there was problem
56
+ status_table.each do |item|
57
+ worst=TransferAgent.session_status(item[STATUS_FIELD])
58
+ global_status=worst unless worst.eql?(:success)
59
+ item[STATUS_FIELD]=item[STATUS_FIELD].map(&:to_s).join(',')
60
+ end
61
+ raise global_status unless global_status.eql?(:success)
62
+ return {type: :object_list,data: status_table}
63
+ end
64
+ end
65
+
66
+ private
67
+
32
68
  # =============================================================
33
69
  # Parameter handlers
34
70
  #
35
- def option_insecure; Rest.insecure ; end
36
-
37
- def option_insecure=(value); Rest.insecure = value; end
71
+ attr_accessor :option_insecure, :option_http_options, :option_cache_tokens
38
72
 
39
73
  def option_ui; OpenApplication.instance.url_method; end
40
74
 
41
75
  def option_ui=(value); OpenApplication.instance.url_method=value; end
42
76
 
77
+ # called everytime a new REST HTTP session is opened
78
+ # @param http [Net::HTTP] the newly created http session object
79
+ def http_parameters=(http)
80
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @option_insecure
81
+ http.set_debug_output($stdout) if @option_rest_debug
82
+ raise 'http_options expects Hash' unless @option_http_options.is_a?(Hash)
83
+
84
+ @option_http_options.each do |k,v|
85
+ method="#{k}=".to_sym
86
+ # check if accessor is a method of Net::HTTP
87
+ # continue_timeout= read_timeout= write_timeout=
88
+ if http.respond_to?(method)
89
+ http.send(method,v)
90
+ else
91
+ Log.log.error("no such attribute: #{k}")
92
+ end
93
+ end
94
+ end
95
+
43
96
  # minimum initialization
44
97
  def initialize(argv)
45
98
  # first thing : manage debug level (allows debugging of option parser)
46
99
  early_debug_setup(argv)
47
100
  # compare $0 with expected name
48
101
  current_prog_name=File.basename($PROGRAM_NAME)
49
- unless current_prog_name.eql?(PROGRAM_NAME)
50
- @plugin_env[:formater].display_message(:error,"#{"WARNING".bg_red.blink.gray} Please use '#{PROGRAM_NAME}' instead of '#{current_prog_name}', '#{current_prog_name}' will be removed in a future version")
51
- end
102
+ @plugin_env[:formater].display_message(:error,"#{'WARNING'.bg_red.blink.gray} Please use '#{PROGRAM_NAME}' instead of '#{current_prog_name}'") unless current_prog_name.eql?(PROGRAM_NAME)
52
103
  @option_help=false
53
104
  @bash_completion=false
54
105
  @option_show_config=false
106
+ @option_insecure=false
107
+ @option_rest_debug=false
108
+ @option_cache_tokens=true
109
+ @option_http_options={}
55
110
  # environment provided to plugin for various capabilities
56
111
  @plugin_env={}
57
- # find out application main folder
58
- app_main_folder=ENV[conf_dir_env_var]
59
- # if env var undefined or empty
60
- if app_main_folder.nil? or app_main_folder.empty?
61
- user_home_folder=Dir.home
62
- raise CliError,"Home folder does not exist: #{user_home_folder}. Check your user environment or use #{conf_dir_env_var}." unless Dir.exist?(user_home_folder)
63
- app_main_folder=File.join(user_home_folder,Plugins::Config::ASPERA_HOME_FOLDER_NAME,PROGRAM_NAME)
64
- end
65
- # give command line arguments to option manager (no parsing)
66
- @plugin_env[:options]=@opt_mgr=Manager.new(PROGRAM_NAME,argv,app_banner())
112
+ # give command line arguments to option manager
113
+ @plugin_env[:options]=@opt_mgr=Manager.new(PROGRAM_NAME,argv)
114
+ # formatter adds options
67
115
  @plugin_env[:formater]=Formater.new(@plugin_env[:options])
68
116
  Rest.user_agent=PROGRAM_NAME
117
+ Rest.session_cb=lambda{|http|self.http_parameters=http}
69
118
  # declare and parse global options
70
119
  init_global_options()
71
- # secret manager
72
- @plugin_env[:secret]=Aspera::Secrets.new
73
- # the Config plugin adds the @preset parser
74
- @plugin_env[:config]=Plugins::Config.new(@plugin_env,PROGRAM_NAME,HELP_URL,Aspera::Cli::VERSION,app_main_folder)
120
+ # the Config plugin adds the @preset parser, so declare before TransferAgent which may use it
121
+ @plugin_env[:config]=Plugins::Config.new(@plugin_env, gem: GEM_NAME, name: PROGRAM_NAME, help: DOC_URL, version: Aspera::Cli::VERSION)
75
122
  # the TransferAgent plugin may use the @preset parser
76
- @plugin_env[:transfer]=TransferAgent.new(@plugin_env)
77
- # set application folder for modules
123
+ @plugin_env[:transfer]=TransferAgent.new(@plugin_env[:options],@plugin_env[:config])
124
+ # data persistency
78
125
  @plugin_env[:persistency]=PersistencyFolder.new(File.join(@plugin_env[:config].main_folder,'persist_store'))
79
126
  Log.log.debug('plugin env created'.red)
80
- Oauth.persist_mgr=@plugin_env[:persistency]
127
+ Oauth.persist_mgr=@plugin_env[:persistency] if @option_cache_tokens
81
128
  Fasp::Parameters.file_list_folder=File.join(@plugin_env[:config].main_folder,'filelists')
82
129
  Aspera::RestErrorAnalyzer.instance.log_file=File.join(@plugin_env[:config].main_folder,'rest_exceptions.log')
83
130
  # register aspera REST call error handlers
84
- Aspera::RestErrorsAspera.registerHandlers
131
+ Aspera::RestErrorsAspera.register_handlers
132
+ # set banner when all environment is created so that additional extended value modifiers are known, e.g. @preset
133
+ @opt_mgr.parser.banner=app_banner
85
134
  end
86
135
 
87
136
  def app_banner
88
- banner = "NAME\n\t#{PROGRAM_NAME} -- a command line tool for Aspera Applications (v#{Aspera::Cli::VERSION})\n\n"
89
- banner << "SYNOPSIS\n"
90
- banner << "\t#{PROGRAM_NAME} COMMANDS [OPTIONS] [ARGS]\n"
91
- banner << "\nDESCRIPTION\n"
92
- banner << "\tUse Aspera application to perform operations on command line.\n"
93
- banner << "\tDocumentation and examples: #{GEM_URL}\n"
94
- banner << "\texecute: #{PROGRAM_NAME} conf doc\n"
95
- banner << "\tor visit: #{HELP_URL}\n"
96
- banner << "\nENVIRONMENT VARIABLES\n"
97
- banner << "\t#{conf_dir_env_var} config folder, default: $HOME/#{Plugins::Config::ASPERA_HOME_FOLDER_NAME}/#{PROGRAM_NAME}\n"
98
- banner << "\t#any option can be set as an environment variable, refer to the manual\n"
99
- banner << "\nCOMMANDS\n"
100
- banner << "\tTo list first level commands, execute: #{PROGRAM_NAME}\n"
101
- banner << "\tNote that commands can be written shortened (provided it is unique).\n"
102
- banner << "\nOPTIONS\n"
103
- banner << "\tOptions begin with a '-' (minus), and value is provided on command line.\n"
104
- banner << "\tSpecial values are supported beginning with special prefix, like: #{ExtendedValue.instance.modifiers.map{|m|"@#{m}:"}.join(' ')}.\n"
105
- banner << "\tDates format is 'DD-MM-YY HH:MM:SS', or 'now' or '-<num>h'\n\n"
106
- banner << "ARGS\n"
107
- banner << "\tSome commands require mandatory arguments, e.g. a path.\n"
137
+ return <<~END_OF_BANNER
138
+ NAME
139
+ \t#{PROGRAM_NAME} -- a command line tool for Aspera Applications (v#{Aspera::Cli::VERSION})
140
+
141
+ SYNOPSIS
142
+ \t#{PROGRAM_NAME} COMMANDS [OPTIONS] [ARGS]
143
+
144
+ DESCRIPTION
145
+ \tUse Aspera application to perform operations on command line.
146
+ \tDocumentation and examples: #{GEM_URL}
147
+ \texecute: #{PROGRAM_NAME} conf doc
148
+ \tor visit: #{DOC_URL}
149
+ \tsource repo: #{SRC_URL}
150
+
151
+ ENVIRONMENT VARIABLES
152
+ \t#{@plugin_env[:config].conf_dir_env_var} config folder, default: $HOME/#{Plugins::Config::ASPERA_HOME_FOLDER_NAME}/#{PROGRAM_NAME}
153
+ \tAny option can be set as an environment variable, refer to the manual
154
+
155
+ COMMANDS
156
+ \tTo list first level commands, execute: #{PROGRAM_NAME}
157
+ \tNote that commands can be written shortened (provided it is unique).
158
+
159
+ OPTIONS
160
+ \tOptions begin with a '-' (minus), and value is provided on command line.
161
+ \tSpecial values are supported beginning with special prefix @pfx:, where pfx is one of:
162
+ \t#{ExtendedValue.instance.modifiers.map(&:to_s).join(', ')}
163
+ \tDates format is 'DD-MM-YY HH:MM:SS', or 'now' or '-<num>h'
164
+
165
+ ARGS
166
+ \tSome commands require mandatory arguments, e.g. a path.
167
+ END_OF_BANNER
108
168
  end
109
169
 
110
170
  # define header for manual
111
171
  def init_global_options
112
- Log.log.debug("init_global_options")
113
- @opt_mgr.add_opt_switch(:help,"-h","Show this message.") { @option_help=true }
114
- @opt_mgr.add_opt_switch(:bash_comp,"generate bash completion for command") { @bash_completion=true }
115
- @opt_mgr.add_opt_switch(:show_config, "Display parameters used for the provided action.") { @option_show_config=true }
116
- @opt_mgr.add_opt_switch(:rest_debug,"-r","more debug for HTTP calls") { Rest.debug=true }
172
+ Log.log.debug('init_global_options')
173
+ @opt_mgr.add_opt_switch(:help,'-h','Show this message.') { @option_help=true }
174
+ @opt_mgr.add_opt_switch(:bash_comp,'generate bash completion for command') { @bash_completion=true }
175
+ @opt_mgr.add_opt_switch(:show_config, 'Display parameters used for the provided action.') { @option_show_config=true }
176
+ @opt_mgr.add_opt_switch(:rest_debug,'-r','more debug for HTTP calls') { @option_rest_debug=true }
117
177
  @opt_mgr.add_opt_switch(:version,'-v','display version') { @plugin_env[:formater].display_message(:data,Aspera::Cli::VERSION);Process.exit(0) }
118
178
  @opt_mgr.add_opt_switch(:warnings,'-w','check for language warnings') { $VERBOSE=true }
119
179
  # handler must be set before declaration
@@ -121,15 +181,21 @@ module Aspera
121
181
  @opt_mgr.set_obj_attr(:logger,Log.instance,:logger_type)
122
182
  @opt_mgr.set_obj_attr(:insecure,self,:option_insecure,:no)
123
183
  @opt_mgr.set_obj_attr(:ui,self,:option_ui)
184
+ @opt_mgr.set_obj_attr(:http_options,self,:option_http_options)
185
+ @opt_mgr.set_obj_attr(:log_secrets,Log.instance,:log_secrets)
186
+ @opt_mgr.set_obj_attr(:cache_tokens,self,:option_cache_tokens)
124
187
  @opt_mgr.add_opt_list(:ui,OpenApplication.user_interfaces,'method to start browser')
125
- @opt_mgr.add_opt_list(:log_level,Log.levels,"Log level")
126
- @opt_mgr.add_opt_list(:logger,Log.logtypes,"log method")
127
- @opt_mgr.add_opt_simple(:lock_port,"prevent dual execution of a command, e.g. in cron")
128
- @opt_mgr.add_opt_simple(:query,"additional filter for API calls (extended value) (some commands)")
129
- @opt_mgr.add_opt_boolean(:insecure,"do not validate HTTPS certificate")
130
- @opt_mgr.add_opt_boolean(:once_only,"process only new items (some commands)")
188
+ @opt_mgr.add_opt_list(:log_level,Log.levels,'Log level')
189
+ @opt_mgr.add_opt_list(:logger,Log.logtypes,'log method')
190
+ @opt_mgr.add_opt_simple(:lock_port,'prevent dual execution of a command, e.g. in cron')
191
+ @opt_mgr.add_opt_simple(:query,'additional filter for API calls (extended value) (some commands)')
192
+ @opt_mgr.add_opt_simple(:http_options,'options for http socket (extended value)')
193
+ @opt_mgr.add_opt_boolean(:insecure,'do not validate HTTPS certificate')
194
+ @opt_mgr.add_opt_boolean(:once_only,'process only new items (some commands)')
195
+ @opt_mgr.add_opt_boolean(:log_secrets,'show passwords in logs')
196
+ @opt_mgr.add_opt_boolean(:cache_tokens,'save and reuse Oauth tokens')
131
197
  @opt_mgr.set_option(:ui,OpenApplication.default_gui_mode)
132
- @opt_mgr.set_option(:once_only,:false)
198
+ @opt_mgr.set_option(:once_only,false)
133
199
  # parse declared options
134
200
  @opt_mgr.parse_options!
135
201
  end
@@ -143,33 +209,23 @@ module Aspera
143
209
  require @plugin_env[:config].plugins[plugin_name_sym][:require_stanza]
144
210
  # load default params only if no param already loaded before plugin instanciation
145
211
  env[:config].add_plugin_default_preset(plugin_name_sym)
146
- command_plugin=Plugins::Config.plugin_new(plugin_name_sym,env)
212
+ command_plugin=Plugins::Config.plugin_class(plugin_name_sym).new(env)
147
213
  Log.log.debug("got #{command_plugin.class}")
148
214
  # TODO: check that ancestor is Plugin?
149
215
  return command_plugin
150
216
  end
151
217
 
152
218
  def generate_bash_completion
153
- if @opt_mgr.get_next_argument("",:multiple,:optional).nil?
219
+ if @opt_mgr.get_next_argument('',:multiple,:optional).nil?
154
220
  @plugin_env[:config].plugins.keys.each{|p|puts p.to_s}
155
221
  else
156
- Log.log.warn("only first level completion so far")
222
+ Log.log.warn('only first level completion so far')
157
223
  end
158
224
  Process.exit(0)
159
225
  end
160
226
 
161
- # expect some list, but nothing to display
162
- def self.result_empty; return {:type => :empty, :data => :nil }; end
163
-
164
- # nothing expected
165
- def self.result_nothing; return {:type => :nothing, :data => :nil }; end
166
-
167
- def self.result_status(status); return {:type => :status, :data => status }; end
168
-
169
- def self.result_success; return result_status('complete'); end
170
-
171
227
  def exit_with_usage(all_plugins)
172
- Log.log.debug("exit_with_usage".bg_red)
228
+ Log.log.debug('exit_with_usage'.bg_red)
173
229
  # display main plugin options
174
230
  @plugin_env[:formater].display_message(:error,@opt_mgr.parser)
175
231
  if all_plugins
@@ -179,10 +235,11 @@ module Aspera
179
235
  # override main option parser with a brand new, to avoid having global options
180
236
  plugin_env=@plugin_env.clone
181
237
  plugin_env[:man_only]=true
182
- plugin_env[:options]=Manager.new(PROGRAM_NAME,[],'')
238
+ plugin_env[:options]=Manager.new(PROGRAM_NAME)
239
+ plugin_env[:options].parser.banner='' # remove default banner
183
240
  get_plugin_instance_with_options(plugin_name_sym,plugin_env)
184
241
  # display generated help for plugin options
185
- @plugin_env[:formater].display_message(:error,plugin_env[:options].parser.to_s)
242
+ @plugin_env[:formater].display_message(:error,plugin_env[:options].parser.help)
186
243
  end
187
244
  end
188
245
  Process.exit(0)
@@ -190,54 +247,21 @@ module Aspera
190
247
 
191
248
  protected
192
249
 
193
- # env var name to override the app's main folder
194
- # default main folder is $HOME/<vendor main app folder>/<program name>
195
- def conf_dir_env_var
196
- return "#{PROGRAM_NAME}_home".upcase
197
- end
198
-
199
250
  # early debug for parser
200
251
  # Note: does not accept shortcuts
201
252
  def early_debug_setup(argv)
202
253
  Log.instance.program_name=PROGRAM_NAME
203
254
  argv.each do |arg|
204
255
  case arg
205
- when '--'
206
- return
207
- when /^--log-level=(.*)/
208
- Log.instance.level = $1.to_sym
209
- when /^--logger=(.*)/
210
- Log.instance.logger_type=$1.to_sym
256
+ when '--' then break
257
+ when /^--log-level=(.*)/ then Log.instance.level = Regexp.last_match(1).to_sym
258
+ when /^--logger=(.*)/ then Log.instance.logger_type=Regexp.last_match(1).to_sym
211
259
  end
212
260
  end
213
261
  end
214
262
 
215
263
  public
216
264
 
217
- # Process statuses of finished transfer sessions
218
- # raise exception if there is one error
219
- # else returns an empty status
220
- def self.result_transfer(statuses)
221
- worst=TransferAgent.session_status(statuses)
222
- raise worst unless worst.eql?(:success)
223
- return Main.result_nothing
224
- end
225
-
226
- # used when one command executes several transfer jobs (each job being possibly multi session)
227
- # @param status_table [Array] [{STATUS_FIELD=>[status array],...},...]
228
- # each element has a key STATUS_FIELD which contains the result of possibly mulmtiple sessions
229
- def self.result_transfer_multiple(status_table)
230
- global_status=:success
231
- # transform status into string and find if there was problem
232
- status_table.each do |item|
233
- worst=TransferAgent.session_status(item[STATUS_FIELD])
234
- global_status=worst unless worst.eql?(:success)
235
- item[STATUS_FIELD]=item[STATUS_FIELD].map{|i|i.to_s}.join(',')
236
- end
237
- raise global_status unless global_status.eql?(:success)
238
- return {:type=>:object_list,:data=>status_table}
239
- end
240
-
241
265
  # this is the main function called by initial script just after constructor
242
266
  def process_command_line
243
267
  Log.log.debug('process_command_line')
@@ -249,17 +273,17 @@ module Aspera
249
273
  # find plugins, shall be after parse! ?
250
274
  @plugin_env[:config].add_plugins_from_lookup_folders
251
275
  # help requested without command ? (plugins must be known here)
252
- exit_with_usage(true) if @option_help and @opt_mgr.command_or_arg_empty?
276
+ exit_with_usage(true) if @option_help && @opt_mgr.command_or_arg_empty?
253
277
  generate_bash_completion if @bash_completion
254
- # load global default options and process
255
- @plugin_env[:config].add_plugin_default_preset(Plugins::Config::CONF_GLOBAL_SYM)
256
- @opt_mgr.parse_options!
257
278
  @plugin_env[:config].periodic_check_newer_gem_version
258
- if @option_show_config and @opt_mgr.command_or_arg_empty?
259
- command_sym=Plugins::Config::CONF_PLUGIN_SYM
279
+ command_sym=
280
+ if @option_show_config && @opt_mgr.command_or_arg_empty?
281
+ Plugins::Config::CONF_PLUGIN_SYM
260
282
  else
261
- command_sym=@opt_mgr.get_next_command(@plugin_env[:config].plugins.keys.dup.unshift(:help))
283
+ @opt_mgr.get_next_command(@plugin_env[:config].plugins.keys.dup.unshift(:help))
262
284
  end
285
+ # command will not be executed, but we need manual
286
+ @opt_mgr.fail_on_missing_mandatory=false if @option_help || @option_show_config
263
287
  # main plugin is not dynamically instanciated
264
288
  case command_sym
265
289
  when :help
@@ -275,8 +299,8 @@ module Aspera
275
299
  # help requested for current plugin
276
300
  exit_with_usage(false) if @option_help
277
301
  if @option_show_config
278
- @plugin_env[:formater].display_results({:type=>:single_object,:data=>@opt_mgr.declared_options(false)})
279
- Process.exit(0)
302
+ @plugin_env[:formater].display_results({type: :single_object,data: @opt_mgr.declared_options(only_defined: true)})
303
+ execute_command=false
280
304
  end
281
305
  # locking for single execution (only after "per plugin" option, in case lock port is there)
282
306
  lock_port=@opt_mgr.get_option(:lock_port,:optional)
@@ -285,7 +309,7 @@ module Aspera
285
309
  # no need to close later, will be freed on process exit. must save in member else it is garbage collected
286
310
  Log.log.debug("Opening lock port #{lock_port.to_i}")
287
311
  @tcp_server=TCPServer.new('127.0.0.1',lock_port.to_i)
288
- rescue => e
312
+ rescue StandardError => e
289
313
  execute_command=false
290
314
  Log.log.warn("Another instance is already running (#{e.message}).")
291
315
  end
@@ -294,40 +318,40 @@ module Aspera
294
318
  @plugin_env[:formater].display_results(command_plugin.execute_action) if execute_command
295
319
  # finish
296
320
  @plugin_env[:transfer].shutdown
297
- rescue CliBadArgument => e; exception_info=[e,'Argument',:usage]
298
- rescue CliNoSuchId => e; exception_info=[e,'Identifier']
299
- rescue CliError => e; exception_info=[e,'Tool',:usage]
300
- rescue Fasp::Error => e; exception_info=[e,'FASP(ascp)']
301
- rescue Aspera::RestCallError => e; exception_info=[e,'Rest']
302
- rescue SocketError => e; exception_info=[e,'Network']
303
- rescue StandardError => e; exception_info=[e,'Other',:debug]
304
- rescue Interrupt => e; exception_info=[e,'Interruption',:debug]
321
+ rescue CliBadArgument => e; exception_info={e: e,t: 'Argument',usage: true}
322
+ rescue CliNoSuchId => e; exception_info={e: e,t: 'Identifier'}
323
+ rescue CliError => e; exception_info={e: e,t: 'Tool',usage: true}
324
+ rescue Fasp::Error => e; exception_info={e: e,t: 'FASP(ascp)'}
325
+ rescue Aspera::RestCallError => e; exception_info={e: e,t: 'Rest'}
326
+ rescue SocketError => e; exception_info={e: e,t: 'Network'}
327
+ rescue StandardError => e; exception_info={e: e,t: 'Other',debug: true}
328
+ rescue Interrupt => e; exception_info={e: e,t: 'Interruption',debug: true}
305
329
  end
306
330
  # cleanup file list files
307
331
  TempFileManager.instance.cleanup
308
332
  # 1- processing of error condition
309
333
  unless exception_info.nil?
310
- @plugin_env[:formater].display_message(:error,"ERROR:".bg_red.gray.blink+" "+exception_info[1]+": "+exception_info[0].message)
311
- @plugin_env[:formater].display_message(:error,"Use '-h' option to get help.") if exception_info[2].eql?(:usage)
312
- if exception_info.first.is_a?(Fasp::Error) and exception_info.first.message.eql?('Remote host is not who we expected')
334
+ @plugin_env[:formater].display_message(:error,"#{ERROR_FLASH} #{exception_info[:t]}: #{exception_info[:e].message}")
335
+ @plugin_env[:formater].display_message(:error,'Use option -h to get help.') if exception_info[:usage]
336
+ if exception_info[:e].is_a?(Fasp::Error) && exception_info[:e].message.eql?('Remote host is not who we expected')
313
337
  @plugin_env[:formater].display_message(:error,"For this specific error, refer to:\n#{SRC_URL}#error-remote-host-is-not-who-we-expected\nAdd this to arguments:\n--ts=@json:'{\"sshfp\":null}'")
314
338
  end
315
339
  end
316
340
  # 2- processing of command not processed (due to exception or bad command line)
317
- if execute_command
341
+ if execute_command || @option_show_config
318
342
  @opt_mgr.final_errors.each do |msg|
319
- @plugin_env[:formater].display_message(:error,"ERROR:".bg_red.gray.blink+" Argument: "+msg)
343
+ @plugin_env[:formater].display_message(:error,"#{ERROR_FLASH} Argument: #{msg}")
344
+ # add code as exception if there is not already an error
345
+ exception_info={e: Exception.new(msg),t: 'UnusedArg'} if exception_info.nil?
320
346
  end
321
347
  end
322
348
  # 3- in case of error, fail the process status
323
349
  unless exception_info.nil?
324
- if Log.instance.level.eql?(:debug)
325
- # will force to show stack trace
326
- raise exception_info[0]
327
- else
328
- @plugin_env[:formater].display_message(:error,"Use '--log-level=debug' to get more details.") if exception_info[2].eql?(:debug)
329
- Process.exit(1)
330
- end
350
+ # show stack trace in debug mode
351
+ raise exception_info[:e] if Log.instance.level.eql?(:debug)
352
+ # else give hint and exit
353
+ @plugin_env[:formater].display_message(:error,'Use --log-level=debug to get more details.') if exception_info[:debug]
354
+ Process.exit(1)
331
355
  end
332
356
  return nil
333
357
  end # process_command_line