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.
- checksums.yaml +4 -4
- data/README.md +2095 -1503
- data/bin/ascli +2 -1
- data/bin/asession +4 -5
- data/docs/test_env.conf +3 -0
- data/examples/aoc.rb +4 -3
- data/examples/faspex4.rb +25 -25
- data/examples/proxy.pac +1 -1
- data/examples/transfer.rb +17 -17
- data/lib/aspera/aoc.rb +238 -185
- data/lib/aspera/ascmd.rb +93 -83
- data/lib/aspera/ats_api.rb +11 -10
- data/lib/aspera/cli/basic_auth_plugin.rb +13 -14
- data/lib/aspera/cli/extended_value.rb +42 -33
- data/lib/aspera/cli/formater.rb +142 -108
- data/lib/aspera/cli/info.rb +17 -0
- data/lib/aspera/cli/listener/line_dump.rb +3 -2
- data/lib/aspera/cli/listener/logger.rb +2 -1
- data/lib/aspera/cli/listener/progress.rb +16 -18
- data/lib/aspera/cli/listener/progress_multi.rb +18 -21
- data/lib/aspera/cli/main.rb +173 -149
- data/lib/aspera/cli/manager.rb +163 -168
- data/lib/aspera/cli/plugin.rb +43 -31
- data/lib/aspera/cli/plugins/alee.rb +6 -6
- data/lib/aspera/cli/plugins/aoc.rb +405 -370
- data/lib/aspera/cli/plugins/ats.rb +86 -79
- data/lib/aspera/cli/plugins/bss.rb +14 -16
- data/lib/aspera/cli/plugins/config.rb +580 -362
- data/lib/aspera/cli/plugins/console.rb +23 -19
- data/lib/aspera/cli/plugins/cos.rb +18 -18
- data/lib/aspera/cli/plugins/faspex.rb +201 -158
- data/lib/aspera/cli/plugins/faspex5.rb +80 -57
- data/lib/aspera/cli/plugins/node.rb +183 -166
- data/lib/aspera/cli/plugins/orchestrator.rb +71 -67
- data/lib/aspera/cli/plugins/preview.rb +92 -96
- data/lib/aspera/cli/plugins/server.rb +79 -75
- data/lib/aspera/cli/plugins/shares.rb +35 -19
- data/lib/aspera/cli/plugins/sync.rb +20 -22
- data/lib/aspera/cli/transfer_agent.rb +76 -113
- data/lib/aspera/cli/version.rb +2 -1
- data/lib/aspera/colors.rb +35 -27
- data/lib/aspera/command_line_builder.rb +48 -34
- data/lib/aspera/cos_node.rb +29 -21
- data/lib/aspera/data_repository.rb +3 -2
- data/lib/aspera/environment.rb +50 -45
- data/lib/aspera/fasp/{manager.rb → agent_base.rb} +28 -25
- data/lib/aspera/fasp/{connect.rb → agent_connect.rb} +52 -43
- data/lib/aspera/fasp/{local.rb → agent_direct.rb} +58 -72
- data/lib/aspera/fasp/{http_gw.rb → agent_httpgw.rb} +37 -43
- data/lib/aspera/fasp/{node.rb → agent_node.rb} +35 -16
- data/lib/aspera/fasp/agent_trsdk.rb +104 -0
- data/lib/aspera/fasp/error.rb +2 -1
- data/lib/aspera/fasp/error_info.rb +68 -52
- data/lib/aspera/fasp/installation.rb +152 -124
- data/lib/aspera/fasp/listener.rb +1 -0
- data/lib/aspera/fasp/parameters.rb +87 -92
- data/lib/aspera/fasp/parameters.yaml +305 -249
- data/lib/aspera/fasp/resume_policy.rb +11 -14
- data/lib/aspera/fasp/transfer_spec.rb +26 -0
- data/lib/aspera/fasp/uri.rb +22 -21
- data/lib/aspera/faspex_gw.rb +55 -89
- data/lib/aspera/hash_ext.rb +4 -3
- data/lib/aspera/id_generator.rb +8 -7
- data/lib/aspera/keychain/encrypted_hash.rb +121 -0
- data/lib/aspera/keychain/macos_security.rb +90 -0
- data/lib/aspera/log.rb +55 -37
- data/lib/aspera/nagios.rb +13 -12
- data/lib/aspera/node.rb +30 -25
- data/lib/aspera/oauth.rb +175 -226
- data/lib/aspera/open_application.rb +4 -3
- data/lib/aspera/persistency_action_once.rb +6 -6
- data/lib/aspera/persistency_folder.rb +5 -9
- data/lib/aspera/preview/file_types.rb +6 -5
- data/lib/aspera/preview/generator.rb +25 -24
- data/lib/aspera/preview/options.rb +16 -14
- data/lib/aspera/preview/utils.rb +98 -98
- data/lib/aspera/{proxy_auto_config.erb.js → proxy_auto_config.js} +23 -31
- data/lib/aspera/proxy_auto_config.rb +111 -20
- data/lib/aspera/rest.rb +154 -135
- data/lib/aspera/rest_call_error.rb +2 -2
- data/lib/aspera/rest_error_analyzer.rb +23 -25
- data/lib/aspera/rest_errors_aspera.rb +15 -14
- data/lib/aspera/ssh.rb +12 -10
- data/lib/aspera/sync.rb +42 -41
- data/lib/aspera/temp_file_manager.rb +18 -14
- data/lib/aspera/timer_limiter.rb +2 -1
- data/lib/aspera/uri_reader.rb +7 -5
- data/lib/aspera/web_auth.rb +79 -76
- metadata +116 -29
- data/docs/Makefile +0 -66
- data/docs/README.erb.md +0 -3973
- data/docs/README.md +0 -13
- data/docs/diagrams.txt +0 -49
- data/docs/doc_tools.rb +0 -58
- data/lib/aspera/api_detector.rb +0 -60
- data/lib/aspera/cli/plugins/shares2.rb +0 -114
- data/lib/aspera/secrets.rb +0 -20
data/lib/aspera/cli/main.rb
CHANGED
|
@@ -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/
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
58
|
-
|
|
59
|
-
#
|
|
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
|
-
#
|
|
72
|
-
@plugin_env[:
|
|
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
|
-
#
|
|
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.
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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(
|
|
113
|
-
@opt_mgr.add_opt_switch(:help,
|
|
114
|
-
@opt_mgr.add_opt_switch(:bash_comp,
|
|
115
|
-
@opt_mgr.add_opt_switch(:show_config,
|
|
116
|
-
@opt_mgr.add_opt_switch(:rest_debug,
|
|
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,
|
|
126
|
-
@opt_mgr.add_opt_list(:logger,Log.logtypes,
|
|
127
|
-
@opt_mgr.add_opt_simple(:lock_port,
|
|
128
|
-
@opt_mgr.add_opt_simple(:query,
|
|
129
|
-
@opt_mgr.
|
|
130
|
-
@opt_mgr.add_opt_boolean(:
|
|
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
|
|
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.
|
|
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(
|
|
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(
|
|
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(
|
|
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.
|
|
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
|
-
|
|
207
|
-
when /^--
|
|
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
|
|
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
|
-
|
|
259
|
-
|
|
279
|
+
command_sym=
|
|
280
|
+
if @option_show_config && @opt_mgr.command_or_arg_empty?
|
|
281
|
+
Plugins::Config::CONF_PLUGIN_SYM
|
|
260
282
|
else
|
|
261
|
-
|
|
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({:
|
|
279
|
-
|
|
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=
|
|
298
|
-
rescue CliNoSuchId => e; exception_info=
|
|
299
|
-
rescue CliError => e; exception_info=
|
|
300
|
-
rescue Fasp::Error => e; exception_info=
|
|
301
|
-
rescue Aspera::RestCallError => e; exception_info=
|
|
302
|
-
rescue SocketError => e; exception_info=
|
|
303
|
-
rescue StandardError => e; exception_info=
|
|
304
|
-
rescue Interrupt => e; exception_info=
|
|
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,"
|
|
311
|
-
@plugin_env[:formater].display_message(:error,
|
|
312
|
-
if exception_info.
|
|
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,"
|
|
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
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
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
|