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