aspera-cli 4.0.0 → 4.2.2
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 +843 -304
- data/bin/dascli +13 -0
- data/docs/Makefile +4 -4
- data/docs/README.erb.md +805 -172
- data/docs/test_env.conf +22 -3
- data/examples/aoc.rb +14 -3
- data/examples/faspex4.rb +89 -0
- data/lib/aspera/aoc.rb +87 -108
- data/lib/aspera/cli/formater.rb +2 -0
- data/lib/aspera/cli/main.rb +89 -49
- data/lib/aspera/cli/plugin.rb +9 -4
- data/lib/aspera/cli/plugins/alee.rb +1 -1
- data/lib/aspera/cli/plugins/aoc.rb +188 -173
- data/lib/aspera/cli/plugins/ats.rb +2 -2
- data/lib/aspera/cli/plugins/config.rb +218 -145
- data/lib/aspera/cli/plugins/console.rb +2 -2
- data/lib/aspera/cli/plugins/faspex.rb +114 -61
- data/lib/aspera/cli/plugins/faspex5.rb +85 -43
- data/lib/aspera/cli/plugins/node.rb +3 -3
- data/lib/aspera/cli/plugins/preview.rb +59 -45
- data/lib/aspera/cli/plugins/server.rb +23 -8
- data/lib/aspera/cli/transfer_agent.rb +77 -49
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/command_line_builder.rb +49 -31
- data/lib/aspera/cos_node.rb +33 -28
- data/lib/aspera/environment.rb +2 -2
- data/lib/aspera/fasp/connect.rb +28 -21
- data/lib/aspera/fasp/http_gw.rb +140 -28
- data/lib/aspera/fasp/installation.rb +93 -46
- data/lib/aspera/fasp/local.rb +88 -45
- data/lib/aspera/fasp/manager.rb +15 -0
- data/lib/aspera/fasp/node.rb +4 -4
- data/lib/aspera/fasp/parameters.rb +59 -101
- data/lib/aspera/fasp/parameters.yaml +531 -0
- data/lib/aspera/fasp/resume_policy.rb +13 -12
- data/lib/aspera/fasp/uri.rb +1 -1
- data/lib/aspera/log.rb +1 -1
- data/lib/aspera/node.rb +61 -1
- data/lib/aspera/oauth.rb +49 -46
- data/lib/aspera/persistency_folder.rb +9 -4
- data/lib/aspera/preview/file_types.rb +53 -21
- data/lib/aspera/preview/generator.rb +3 -3
- data/lib/aspera/rest.rb +29 -18
- data/lib/aspera/secrets.rb +20 -0
- data/lib/aspera/sync.rb +40 -35
- data/lib/aspera/temp_file_manager.rb +19 -0
- data/lib/aspera/web_auth.rb +105 -0
- metadata +54 -20
- data/docs/transfer_spec.html +0 -99
data/lib/aspera/cli/main.rb
CHANGED
@@ -10,6 +10,7 @@ require 'aspera/persistency_folder'
|
|
10
10
|
require 'aspera/log'
|
11
11
|
require 'aspera/rest'
|
12
12
|
require 'aspera/nagios'
|
13
|
+
require 'aspera/secrets'
|
13
14
|
|
14
15
|
module Aspera
|
15
16
|
module Cli
|
@@ -20,15 +21,17 @@ module Aspera
|
|
20
21
|
private
|
21
22
|
# name of application, also foldername where config is stored
|
22
23
|
PROGRAM_NAME = 'ascli'
|
24
|
+
# name of the containing gem, same as in <gem name>.gemspec
|
23
25
|
GEM_NAME = 'aspera-cli'
|
24
|
-
|
25
|
-
|
26
|
-
|
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"
|
29
|
+
STATUS_FIELD = 'status'
|
27
30
|
|
31
|
+
private_constant :PROGRAM_NAME,:GEM_NAME,:HELP_URL,:GEM_URL
|
28
32
|
# =============================================================
|
29
33
|
# Parameter handlers
|
30
34
|
#
|
31
|
-
|
32
35
|
def option_insecure; Rest.insecure ; end
|
33
36
|
|
34
37
|
def option_insecure=(value); Rest.insecure = value; end
|
@@ -39,32 +42,41 @@ module Aspera
|
|
39
42
|
|
40
43
|
# minimum initialization
|
41
44
|
def initialize(argv)
|
42
|
-
# first thing : manage debug level (allows debugging
|
45
|
+
# first thing : manage debug level (allows debugging of option parser)
|
43
46
|
early_debug_setup(argv)
|
47
|
+
# compare $0 with expected name
|
44
48
|
current_prog_name=File.basename($PROGRAM_NAME)
|
45
49
|
unless current_prog_name.eql?(PROGRAM_NAME)
|
46
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")
|
47
51
|
end
|
48
|
-
# overriding parameters on transfer spec
|
49
52
|
@option_help=false
|
50
53
|
@bash_completion=false
|
51
54
|
@option_show_config=false
|
55
|
+
# environment provided to plugin for various capabilities
|
52
56
|
@plugin_env={}
|
53
|
-
|
54
|
-
|
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
|
55
65
|
# give command line arguments to option manager (no parsing)
|
56
|
-
@plugin_env[:options]=@opt_mgr=Manager.new(
|
66
|
+
@plugin_env[:options]=@opt_mgr=Manager.new(PROGRAM_NAME,argv,app_banner())
|
57
67
|
@plugin_env[:formater]=Formater.new(@plugin_env[:options])
|
58
|
-
Rest.user_agent=
|
59
|
-
#
|
68
|
+
Rest.user_agent=PROGRAM_NAME
|
69
|
+
# declare and parse global options
|
60
70
|
init_global_options()
|
71
|
+
# secret manager
|
72
|
+
@plugin_env[:secret]=Aspera::Secrets.new
|
61
73
|
# the Config plugin adds the @preset parser
|
62
|
-
@plugin_env[:config]=Plugins::Config.new(@plugin_env,
|
74
|
+
@plugin_env[:config]=Plugins::Config.new(@plugin_env,PROGRAM_NAME,HELP_URL,Aspera::Cli::VERSION,app_main_folder)
|
63
75
|
# the TransferAgent plugin may use the @preset parser
|
64
76
|
@plugin_env[:transfer]=TransferAgent.new(@plugin_env)
|
65
|
-
Log.log.debug('created plugin env'.red)
|
66
77
|
# set application folder for modules
|
67
78
|
@plugin_env[:persistency]=PersistencyFolder.new(File.join(@plugin_env[:config].main_folder,'persist_store'))
|
79
|
+
Log.log.debug('plugin env created'.red)
|
68
80
|
Oauth.persist_mgr=@plugin_env[:persistency]
|
69
81
|
Fasp::Parameters.file_list_folder=File.join(@plugin_env[:config].main_folder,'filelists')
|
70
82
|
Aspera::RestErrorAnalyzer.instance.log_file=File.join(@plugin_env[:config].main_folder,'rest_exceptions.log')
|
@@ -73,21 +85,21 @@ module Aspera
|
|
73
85
|
end
|
74
86
|
|
75
87
|
def app_banner
|
76
|
-
banner = "NAME\n\t#{
|
88
|
+
banner = "NAME\n\t#{PROGRAM_NAME} -- a command line tool for Aspera Applications (v#{Aspera::Cli::VERSION})\n\n"
|
77
89
|
banner << "SYNOPSIS\n"
|
78
|
-
banner << "\t#{
|
79
|
-
banner << "\n"
|
80
|
-
banner << "DESCRIPTION\n"
|
90
|
+
banner << "\t#{PROGRAM_NAME} COMMANDS [OPTIONS] [ARGS]\n"
|
91
|
+
banner << "\nDESCRIPTION\n"
|
81
92
|
banner << "\tUse Aspera application to perform operations on command line.\n"
|
82
|
-
banner << "\tDocumentation and examples: #{
|
83
|
-
banner << "\texecute: #{
|
84
|
-
banner << "\tor visit: #{
|
85
|
-
banner << "\n"
|
86
|
-
banner << "
|
87
|
-
banner << "\
|
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"
|
88
101
|
banner << "\tNote that commands can be written shortened (provided it is unique).\n"
|
89
|
-
banner << "\n"
|
90
|
-
banner << "OPTIONS\n"
|
102
|
+
banner << "\nOPTIONS\n"
|
91
103
|
banner << "\tOptions begin with a '-' (minus), and value is provided on command line.\n"
|
92
104
|
banner << "\tSpecial values are supported beginning with special prefix, like: #{ExtendedValue.instance.modifiers.map{|m|"@#{m}:"}.join(' ')}.\n"
|
93
105
|
banner << "\tDates format is 'DD-MM-YY HH:MM:SS', or 'now' or '-<num>h'\n\n"
|
@@ -167,7 +179,7 @@ module Aspera
|
|
167
179
|
# override main option parser with a brand new, to avoid having global options
|
168
180
|
plugin_env=@plugin_env.clone
|
169
181
|
plugin_env[:man_only]=true
|
170
|
-
plugin_env[:options]=Manager.new(
|
182
|
+
plugin_env[:options]=Manager.new(PROGRAM_NAME,[],'')
|
171
183
|
get_plugin_instance_with_options(plugin_name_sym,plugin_env)
|
172
184
|
# display generated help for plugin options
|
173
185
|
@plugin_env[:formater].display_message(:error,plugin_env[:options].parser.to_s)
|
@@ -178,10 +190,16 @@ module Aspera
|
|
178
190
|
|
179
191
|
protected
|
180
192
|
|
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
|
+
|
181
199
|
# early debug for parser
|
182
200
|
# Note: does not accept shortcuts
|
183
201
|
def early_debug_setup(argv)
|
184
|
-
Log.instance.program_name=
|
202
|
+
Log.instance.program_name=PROGRAM_NAME
|
185
203
|
argv.each do |arg|
|
186
204
|
case arg
|
187
205
|
when '--'
|
@@ -205,14 +223,28 @@ module Aspera
|
|
205
223
|
return Main.result_nothing
|
206
224
|
end
|
207
225
|
|
208
|
-
|
209
|
-
|
210
|
-
|
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
|
211
240
|
|
212
241
|
# this is the main function called by initial script just after constructor
|
213
242
|
def process_command_line
|
214
243
|
Log.log.debug('process_command_line')
|
244
|
+
# catch exception information , if any
|
215
245
|
exception_info=nil
|
246
|
+
# false if command shall not be executed ("once_only")
|
247
|
+
execute_command=true
|
216
248
|
begin
|
217
249
|
# find plugins, shall be after parse! ?
|
218
250
|
@plugin_env[:config].add_plugins_from_lookup_folders
|
@@ -222,16 +254,7 @@ module Aspera
|
|
222
254
|
# load global default options and process
|
223
255
|
@plugin_env[:config].add_plugin_default_preset(Plugins::Config::CONF_GLOBAL_SYM)
|
224
256
|
@opt_mgr.parse_options!
|
225
|
-
|
226
|
-
lock_port=@opt_mgr.get_option(:lock_port,:optional)
|
227
|
-
if !lock_port.nil?
|
228
|
-
begin
|
229
|
-
# no need to close later, will be freed on process exit. must save in member else it is garbage collected
|
230
|
-
@tcp_server=TCPServer.new('127.0.0.1',lock_port.to_i)
|
231
|
-
rescue => e
|
232
|
-
raise CliError,"Another instance is already running (lock port=#{lock_port})."
|
233
|
-
end
|
234
|
-
end
|
257
|
+
@plugin_env[:config].periodic_check_newer_gem_version
|
235
258
|
if @option_show_config and @opt_mgr.command_or_arg_empty?
|
236
259
|
command_sym=Plugins::Config::CONF_PLUGIN_SYM
|
237
260
|
else
|
@@ -255,18 +278,30 @@ module Aspera
|
|
255
278
|
@plugin_env[:formater].display_results({:type=>:single_object,:data=>@opt_mgr.declared_options(false)})
|
256
279
|
Process.exit(0)
|
257
280
|
end
|
258
|
-
#
|
259
|
-
|
281
|
+
# locking for single execution (only after "per plugin" option, in case lock port is there)
|
282
|
+
lock_port=@opt_mgr.get_option(:lock_port,:optional)
|
283
|
+
if !lock_port.nil?
|
284
|
+
begin
|
285
|
+
# no need to close later, will be freed on process exit. must save in member else it is garbage collected
|
286
|
+
Log.log.debug("Opening lock port #{lock_port.to_i}")
|
287
|
+
@tcp_server=TCPServer.new('127.0.0.1',lock_port.to_i)
|
288
|
+
rescue => e
|
289
|
+
execute_command=false
|
290
|
+
Log.log.warn("Another instance is already running (#{e.message}).")
|
291
|
+
end
|
292
|
+
end
|
293
|
+
# execute and display (if not exclusive execution)
|
294
|
+
@plugin_env[:formater].display_results(command_plugin.execute_action) if execute_command
|
260
295
|
# finish
|
261
296
|
@plugin_env[:transfer].shutdown
|
262
297
|
rescue CliBadArgument => e; exception_info=[e,'Argument',:usage]
|
263
298
|
rescue CliNoSuchId => e; exception_info=[e,'Identifier']
|
264
299
|
rescue CliError => e; exception_info=[e,'Tool',:usage]
|
265
|
-
rescue Fasp::Error => e; exception_info=[e,
|
266
|
-
rescue Aspera::RestCallError => e;
|
267
|
-
rescue SocketError => e; exception_info=[e,
|
268
|
-
rescue StandardError => e; exception_info=[e,
|
269
|
-
rescue Interrupt => e; exception_info=[e,
|
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]
|
270
305
|
end
|
271
306
|
# cleanup file list files
|
272
307
|
TempFileManager.instance.cleanup
|
@@ -274,10 +309,15 @@ module Aspera
|
|
274
309
|
unless exception_info.nil?
|
275
310
|
@plugin_env[:formater].display_message(:error,"ERROR:".bg_red.gray.blink+" "+exception_info[1]+": "+exception_info[0].message)
|
276
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')
|
313
|
+
@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
|
+
end
|
277
315
|
end
|
278
316
|
# 2- processing of command not processed (due to exception or bad command line)
|
279
|
-
|
280
|
-
@
|
317
|
+
if execute_command
|
318
|
+
@opt_mgr.final_errors.each do |msg|
|
319
|
+
@plugin_env[:formater].display_message(:error,"ERROR:".bg_red.gray.blink+" Argument: "+msg)
|
320
|
+
end
|
281
321
|
end
|
282
322
|
# 3- in case of error, fail the process status
|
283
323
|
unless exception_info.nil?
|
data/lib/aspera/cli/plugin.rb
CHANGED
@@ -67,7 +67,10 @@ module Aspera
|
|
67
67
|
when :delete
|
68
68
|
rest_api.delete(one_res_path)
|
69
69
|
return Main.result_status("deleted")
|
70
|
+
else
|
71
|
+
raise "unknown action: #{command}"
|
70
72
|
end
|
73
|
+
raise "internal error should not reach here"
|
71
74
|
end
|
72
75
|
|
73
76
|
# implement generic rest operations on given resource path
|
@@ -77,13 +80,15 @@ module Aspera
|
|
77
80
|
return entity_command(command,rest_api,res_class_path,display_fields,id_symb,id_default,subkey)
|
78
81
|
end
|
79
82
|
|
80
|
-
def options
|
83
|
+
def options; return @agents[:options];end
|
81
84
|
|
82
|
-
def transfer
|
85
|
+
def transfer; return @agents[:transfer];end
|
83
86
|
|
84
|
-
def config;return @agents[:config];end
|
87
|
+
def config; return @agents[:config];end
|
85
88
|
|
86
|
-
def format;return @agents[:formater];end
|
89
|
+
def format; return @agents[:formater];end
|
90
|
+
|
91
|
+
def persistency; return @agents[:persistency];end
|
87
92
|
|
88
93
|
end # Plugin
|
89
94
|
end # Cli
|
@@ -12,7 +12,7 @@ module Aspera
|
|
12
12
|
command=self.options.get_next_command(ACTIONS)
|
13
13
|
case command
|
14
14
|
when :entitlement
|
15
|
-
entitlement_id = self.options.get_option(:username,:mandatory)
|
15
|
+
entitlement_id = self.options.get_option(:username,:mandatory)
|
16
16
|
customer_id = self.options.get_option(:password,:mandatory)
|
17
17
|
api_metering=AoC.metering_api(entitlement_id,customer_id)
|
18
18
|
return {:type=>:single_object, :data=>api_metering.read('entitlement')[:data]}
|