aspera-cli 4.4.0 → 4.5.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 +1042 -787
- data/bin/ascli +1 -1
- data/bin/asession +3 -5
- data/docs/Makefile +4 -7
- data/docs/README.erb.md +988 -740
- data/examples/faspex4.rb +4 -6
- data/examples/transfer.rb +2 -2
- data/lib/aspera/aoc.rb +139 -118
- data/lib/aspera/cli/listener/progress_multi.rb +5 -5
- data/lib/aspera/cli/main.rb +64 -34
- data/lib/aspera/cli/manager.rb +19 -20
- data/lib/aspera/cli/plugin.rb +9 -1
- data/lib/aspera/cli/plugins/aoc.rb +156 -143
- data/lib/aspera/cli/plugins/ats.rb +11 -10
- data/lib/aspera/cli/plugins/bss.rb +2 -2
- data/lib/aspera/cli/plugins/config.rb +236 -112
- data/lib/aspera/cli/plugins/faspex.rb +29 -7
- data/lib/aspera/cli/plugins/faspex5.rb +21 -8
- data/lib/aspera/cli/plugins/node.rb +21 -9
- data/lib/aspera/cli/plugins/orchestrator.rb +5 -3
- data/lib/aspera/cli/plugins/preview.rb +2 -2
- data/lib/aspera/cli/plugins/server.rb +3 -3
- data/lib/aspera/cli/plugins/shares.rb +17 -0
- data/lib/aspera/cli/transfer_agent.rb +47 -85
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/environment.rb +4 -4
- data/lib/aspera/fasp/{manager.rb → agent_base.rb} +7 -6
- data/lib/aspera/fasp/{connect.rb → agent_connect.rb} +46 -39
- data/lib/aspera/fasp/{local.rb → agent_direct.rb} +14 -17
- data/lib/aspera/fasp/{http_gw.rb → agent_httpgw.rb} +4 -4
- data/lib/aspera/fasp/{node.rb → agent_node.rb} +25 -8
- data/lib/aspera/fasp/agent_trsdk.rb +106 -0
- data/lib/aspera/fasp/default.rb +17 -0
- data/lib/aspera/fasp/installation.rb +64 -48
- data/lib/aspera/fasp/parameters.rb +7 -3
- data/lib/aspera/faspex_gw.rb +6 -6
- data/lib/aspera/keychain/encrypted_hash.rb +120 -0
- data/lib/aspera/keychain/macos_security.rb +94 -0
- data/lib/aspera/log.rb +45 -32
- data/lib/aspera/node.rb +3 -6
- data/lib/aspera/rest.rb +65 -49
- metadata +68 -27
- data/lib/aspera/api_detector.rb +0 -60
- data/lib/aspera/secrets.rb +0 -20
data/lib/aspera/cli/main.rb
CHANGED
@@ -4,42 +4,57 @@ require 'aspera/cli/plugins/config'
|
|
4
4
|
require 'aspera/cli/extended_value'
|
5
5
|
require 'aspera/cli/transfer_agent'
|
6
6
|
require 'aspera/cli/version'
|
7
|
+
require 'aspera/fasp/error'
|
7
8
|
require 'aspera/open_application'
|
8
9
|
require 'aspera/temp_file_manager'
|
9
10
|
require 'aspera/persistency_folder'
|
10
11
|
require 'aspera/log'
|
11
12
|
require 'aspera/rest'
|
12
13
|
require 'aspera/nagios'
|
13
|
-
require 'aspera/secrets'
|
14
14
|
|
15
15
|
module Aspera
|
16
16
|
module Cli
|
17
17
|
# The main CLI class
|
18
18
|
class Main
|
19
19
|
|
20
|
-
attr_reader :plugin_env
|
21
20
|
private
|
22
|
-
# name of application, also foldername where config is stored
|
21
|
+
# name of application, also used as foldername where config is stored
|
23
22
|
PROGRAM_NAME = 'ascli'
|
24
23
|
# name of the containing gem, same as in <gem name>.gemspec
|
25
24
|
GEM_NAME = 'aspera-cli'
|
26
25
|
HELP_URL = "http://www.rubydoc.info/gems/#{GEM_NAME}"
|
27
26
|
GEM_URL = "https://rubygems.org/gems/#{GEM_NAME}"
|
28
|
-
SRC_URL =
|
27
|
+
SRC_URL = 'https://github.com/IBM/aspera-cli'
|
28
|
+
# store transfer result using this key and use result_transfer_multiple
|
29
29
|
STATUS_FIELD = 'status'
|
30
30
|
|
31
31
|
private_constant :PROGRAM_NAME,:GEM_NAME,:HELP_URL,:GEM_URL
|
32
32
|
# =============================================================
|
33
33
|
# Parameter handlers
|
34
34
|
#
|
35
|
-
|
36
|
-
|
37
|
-
def option_insecure=(value); Rest.insecure = value; end
|
38
|
-
|
35
|
+
attr_accessor :option_insecure, :option_http_options
|
39
36
|
def option_ui; OpenApplication.instance.url_method; end
|
40
37
|
|
41
38
|
def option_ui=(value); OpenApplication.instance.url_method=value; end
|
42
39
|
|
40
|
+
# called everytime a new REST HTTP session is opened
|
41
|
+
# @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
|
44
|
+
http.set_debug_output($stdout) if @option_rest_debug
|
45
|
+
raise "http_options expects Hash" unless @option_http_options.is_a?(Hash)
|
46
|
+
@option_http_options.each do |k,v|
|
47
|
+
method="#{k}=".to_sym
|
48
|
+
# check if accessor is a method of Net::HTTP
|
49
|
+
# continue_timeout= read_timeout= write_timeout=
|
50
|
+
if http.respond_to?(method)
|
51
|
+
http.send(method,v)
|
52
|
+
else
|
53
|
+
Log.log.error("no such attribute: #{k}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
43
58
|
# minimum initialization
|
44
59
|
def initialize(argv)
|
45
60
|
# first thing : manage debug level (allows debugging of option parser)
|
@@ -52,29 +67,24 @@ module Aspera
|
|
52
67
|
@option_help=false
|
53
68
|
@bash_completion=false
|
54
69
|
@option_show_config=false
|
70
|
+
@option_insecure=false
|
71
|
+
@option_rest_debug=false
|
72
|
+
@option_http_options={}
|
55
73
|
# environment provided to plugin for various capabilities
|
56
74
|
@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())
|
75
|
+
# give command line arguments to option manager
|
76
|
+
@plugin_env[:options]=@opt_mgr=Manager.new(PROGRAM_NAME,argv)
|
77
|
+
# formatter adds options
|
67
78
|
@plugin_env[:formater]=Formater.new(@plugin_env[:options])
|
68
79
|
Rest.user_agent=PROGRAM_NAME
|
80
|
+
Rest.session_cb=lambda {|http| set_http_parameters(http)}
|
69
81
|
# declare and parse global options
|
70
82
|
init_global_options()
|
71
|
-
#
|
72
|
-
@plugin_env[:secret]=Aspera::Secrets.new
|
73
|
-
# the Config plugin adds the @preset parser
|
83
|
+
# the Config plugin adds the @preset parser, so declare before TransferAgent which may use it
|
74
84
|
@plugin_env[:config]=Plugins::Config.new(@plugin_env,PROGRAM_NAME,HELP_URL,Aspera::Cli::VERSION,app_main_folder)
|
75
85
|
# the TransferAgent plugin may use the @preset parser
|
76
|
-
@plugin_env[:transfer]=TransferAgent.new(@plugin_env)
|
77
|
-
#
|
86
|
+
@plugin_env[:transfer]=TransferAgent.new(@plugin_env[:options],@plugin_env[:config])
|
87
|
+
# data persistency
|
78
88
|
@plugin_env[:persistency]=PersistencyFolder.new(File.join(@plugin_env[:config].main_folder,'persist_store'))
|
79
89
|
Log.log.debug('plugin env created'.red)
|
80
90
|
Oauth.persist_mgr=@plugin_env[:persistency]
|
@@ -82,6 +92,8 @@ module Aspera
|
|
82
92
|
Aspera::RestErrorAnalyzer.instance.log_file=File.join(@plugin_env[:config].main_folder,'rest_exceptions.log')
|
83
93
|
# register aspera REST call error handlers
|
84
94
|
Aspera::RestErrorsAspera.registerHandlers
|
95
|
+
# 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
|
85
97
|
end
|
86
98
|
|
87
99
|
def app_banner
|
@@ -93,15 +105,16 @@ module Aspera
|
|
93
105
|
banner << "\tDocumentation and examples: #{GEM_URL}\n"
|
94
106
|
banner << "\texecute: #{PROGRAM_NAME} conf doc\n"
|
95
107
|
banner << "\tor visit: #{HELP_URL}\n"
|
108
|
+
banner << "\tsource repo: #{SRC_URL}\n"
|
96
109
|
banner << "\nENVIRONMENT VARIABLES\n"
|
97
110
|
banner << "\t#{conf_dir_env_var} config folder, default: $HOME/#{Plugins::Config::ASPERA_HOME_FOLDER_NAME}/#{PROGRAM_NAME}\n"
|
98
|
-
banner << "\
|
111
|
+
banner << "\tany option can be set as an environment variable, refer to the manual\n"
|
99
112
|
banner << "\nCOMMANDS\n"
|
100
113
|
banner << "\tTo list first level commands, execute: #{PROGRAM_NAME}\n"
|
101
114
|
banner << "\tNote that commands can be written shortened (provided it is unique).\n"
|
102
115
|
banner << "\nOPTIONS\n"
|
103
116
|
banner << "\tOptions begin with a '-' (minus), and value is provided on command line.\n"
|
104
|
-
banner << "\tSpecial values are supported beginning with special prefix
|
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"
|
105
118
|
banner << "\tDates format is 'DD-MM-YY HH:MM:SS', or 'now' or '-<num>h'\n\n"
|
106
119
|
banner << "ARGS\n"
|
107
120
|
banner << "\tSome commands require mandatory arguments, e.g. a path.\n"
|
@@ -113,7 +126,7 @@ module Aspera
|
|
113
126
|
@opt_mgr.add_opt_switch(:help,"-h","Show this message.") { @option_help=true }
|
114
127
|
@opt_mgr.add_opt_switch(:bash_comp,"generate bash completion for command") { @bash_completion=true }
|
115
128
|
@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") {
|
129
|
+
@opt_mgr.add_opt_switch(:rest_debug,"-r","more debug for HTTP calls") { @option_rest_debug=true }
|
117
130
|
@opt_mgr.add_opt_switch(:version,'-v','display version') { @plugin_env[:formater].display_message(:data,Aspera::Cli::VERSION);Process.exit(0) }
|
118
131
|
@opt_mgr.add_opt_switch(:warnings,'-w','check for language warnings') { $VERBOSE=true }
|
119
132
|
# handler must be set before declaration
|
@@ -121,13 +134,17 @@ module Aspera
|
|
121
134
|
@opt_mgr.set_obj_attr(:logger,Log.instance,:logger_type)
|
122
135
|
@opt_mgr.set_obj_attr(:insecure,self,:option_insecure,:no)
|
123
136
|
@opt_mgr.set_obj_attr(:ui,self,:option_ui)
|
137
|
+
@opt_mgr.set_obj_attr(:http_options,self,:option_http_options)
|
138
|
+
@opt_mgr.set_obj_attr(:log_passwords,Log.instance,:log_passwords)
|
124
139
|
@opt_mgr.add_opt_list(:ui,OpenApplication.user_interfaces,'method to start browser')
|
125
140
|
@opt_mgr.add_opt_list(:log_level,Log.levels,"Log level")
|
126
141
|
@opt_mgr.add_opt_list(:logger,Log.logtypes,"log method")
|
127
142
|
@opt_mgr.add_opt_simple(:lock_port,"prevent dual execution of a command, e.g. in cron")
|
128
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)")
|
129
145
|
@opt_mgr.add_opt_boolean(:insecure,"do not validate HTTPS certificate")
|
130
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")
|
131
148
|
@opt_mgr.set_option(:ui,OpenApplication.default_gui_mode)
|
132
149
|
@opt_mgr.set_option(:once_only,:false)
|
133
150
|
# parse declared options
|
@@ -143,7 +160,7 @@ module Aspera
|
|
143
160
|
require @plugin_env[:config].plugins[plugin_name_sym][:require_stanza]
|
144
161
|
# load default params only if no param already loaded before plugin instanciation
|
145
162
|
env[:config].add_plugin_default_preset(plugin_name_sym)
|
146
|
-
command_plugin=Plugins::Config.
|
163
|
+
command_plugin=Plugins::Config.plugin_class(plugin_name_sym).new(env)
|
147
164
|
Log.log.debug("got #{command_plugin.class}")
|
148
165
|
# TODO: check that ancestor is Plugin?
|
149
166
|
return command_plugin
|
@@ -179,10 +196,11 @@ module Aspera
|
|
179
196
|
# override main option parser with a brand new, to avoid having global options
|
180
197
|
plugin_env=@plugin_env.clone
|
181
198
|
plugin_env[:man_only]=true
|
182
|
-
plugin_env[:options]=Manager.new(PROGRAM_NAME
|
199
|
+
plugin_env[:options]=Manager.new(PROGRAM_NAME)
|
200
|
+
plugin_env[:options].parser.banner='' # remove default banner
|
183
201
|
get_plugin_instance_with_options(plugin_name_sym,plugin_env)
|
184
202
|
# display generated help for plugin options
|
185
|
-
@plugin_env[:formater].display_message(:error,plugin_env[:options].parser.
|
203
|
+
@plugin_env[:formater].display_message(:error,plugin_env[:options].parser.help)
|
186
204
|
end
|
187
205
|
end
|
188
206
|
Process.exit(0)
|
@@ -196,6 +214,18 @@ module Aspera
|
|
196
214
|
return "#{PROGRAM_NAME}_home".upcase
|
197
215
|
end
|
198
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
|
+
|
199
229
|
# early debug for parser
|
200
230
|
# Note: does not accept shortcuts
|
201
231
|
def early_debug_setup(argv)
|
@@ -225,10 +255,11 @@ module Aspera
|
|
225
255
|
|
226
256
|
# used when one command executes several transfer jobs (each job being possibly multi session)
|
227
257
|
# @param status_table [Array] [{STATUS_FIELD=>[status array],...},...]
|
228
|
-
#
|
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
|
229
260
|
def self.result_transfer_multiple(status_table)
|
230
261
|
global_status=:success
|
231
|
-
# transform status into string and find if there was problem
|
262
|
+
# transform status array into string and find if there was problem
|
232
263
|
status_table.each do |item|
|
233
264
|
worst=TransferAgent.session_status(item[STATUS_FIELD])
|
234
265
|
global_status=worst unless worst.eql?(:success)
|
@@ -251,9 +282,6 @@ module Aspera
|
|
251
282
|
# help requested without command ? (plugins must be known here)
|
252
283
|
exit_with_usage(true) if @option_help and @opt_mgr.command_or_arg_empty?
|
253
284
|
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
285
|
@plugin_env[:config].periodic_check_newer_gem_version
|
258
286
|
if @option_show_config and @opt_mgr.command_or_arg_empty?
|
259
287
|
command_sym=Plugins::Config::CONF_PLUGIN_SYM
|
@@ -317,6 +345,8 @@ module Aspera
|
|
317
345
|
if execute_command
|
318
346
|
@opt_mgr.final_errors.each do |msg|
|
319
347
|
@plugin_env[:formater].display_message(:error,"ERROR:".bg_red.gray.blink+" Argument: "+msg)
|
348
|
+
# add code as exception if there is not already an error
|
349
|
+
exception_info=[Exception.new(msg),'UnusedArg'] if exception_info.nil?
|
320
350
|
end
|
321
351
|
end
|
322
352
|
# 3- in case of error, fail the process status
|
data/lib/aspera/cli/manager.rb
CHANGED
@@ -79,7 +79,7 @@ module Aspera
|
|
79
79
|
attr_accessor :ask_missing_optional
|
80
80
|
|
81
81
|
#
|
82
|
-
def initialize(program_name,argv
|
82
|
+
def initialize(program_name,argv=nil)
|
83
83
|
# command line values not starting with '-'
|
84
84
|
@unprocessed_cmd_line_arguments=[]
|
85
85
|
# command line values starting with '-'
|
@@ -98,7 +98,6 @@ module Aspera
|
|
98
98
|
# Note: was initially inherited but it is prefered to have specific methods
|
99
99
|
@parser=OptionParser.new
|
100
100
|
@parser.program_name=program_name
|
101
|
-
@parser.banner=app_banner
|
102
101
|
# options can also be provided by env vars : --param-name -> ASLMCLI_PARAM_NAME
|
103
102
|
env_prefix=program_name.upcase+OPTION_SEP_NAME
|
104
103
|
ENV.each do |k,v|
|
@@ -107,29 +106,29 @@ module Aspera
|
|
107
106
|
end
|
108
107
|
end
|
109
108
|
Log.log.debug("env=#{@unprocessed_env}".red)
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
109
|
+
@unprocessed_cmd_line_options=[]
|
110
|
+
@unprocessed_cmd_line_arguments=[]
|
111
|
+
# argv is nil when help is generated for every plugin
|
112
|
+
unless argv.nil?
|
113
|
+
@parser.separator('')
|
114
|
+
@parser.separator('OPTIONS: global')
|
114
115
|
self.set_obj_attr(:interactive,self,:ask_missing_mandatory)
|
115
116
|
self.set_obj_attr(:ask_options,self,:ask_missing_optional)
|
116
|
-
self.add_opt_boolean(:interactive,
|
117
|
-
self.add_opt_boolean(:ask_options,
|
117
|
+
self.add_opt_boolean(:interactive,'use interactive input of missing params')
|
118
|
+
self.add_opt_boolean(:ask_options,'ask even optional options')
|
118
119
|
self.parse_options!
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
120
|
+
process_options=true
|
121
|
+
while !argv.empty?
|
122
|
+
value=argv.shift
|
123
|
+
if process_options and value.start_with?('-')
|
124
|
+
if value.eql?('--')
|
125
|
+
process_options=false
|
126
|
+
else
|
127
|
+
@unprocessed_cmd_line_options.push(value)
|
128
|
+
end
|
128
129
|
else
|
129
|
-
@
|
130
|
+
@unprocessed_cmd_line_arguments.push(value)
|
130
131
|
end
|
131
|
-
else
|
132
|
-
@unprocessed_cmd_line_arguments.push(value)
|
133
132
|
end
|
134
133
|
end
|
135
134
|
@initial_cli_options=@unprocessed_cmd_line_options.dup
|
data/lib/aspera/cli/plugin.rb
CHANGED
@@ -33,10 +33,18 @@ module Aspera
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
# must be called AFTER the instance action
|
37
|
+
def instance_identifier()
|
38
|
+
res_id=self.options.get_option(:id)
|
39
|
+
res_id=self.options.get_next_argument('identifier') if res_id.nil?
|
40
|
+
return res_id
|
41
|
+
end
|
42
|
+
|
36
43
|
def entity_command(command,rest_api,res_class_path,display_fields,id_symb,id_default=nil,use_subkey=false)
|
44
|
+
raise "not id" unless :id.eql?(id_symb)
|
37
45
|
if INSTANCE_OPS.include?(command)
|
38
46
|
begin
|
39
|
-
one_res_id=
|
47
|
+
one_res_id=instance_identifier()
|
40
48
|
rescue => e
|
41
49
|
raise e if id_default.nil?
|
42
50
|
one_res_id=id_default
|