aspera-cli 4.2.1 → 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 +1580 -946
- data/bin/ascli +1 -1
- data/bin/asession +3 -5
- data/docs/Makefile +8 -11
- data/docs/README.erb.md +1521 -829
- data/docs/doc_tools.rb +58 -0
- data/docs/test_env.conf +3 -1
- data/examples/faspex4.rb +28 -19
- data/examples/transfer.rb +2 -2
- data/lib/aspera/aoc.rb +157 -134
- data/lib/aspera/cli/listener/progress_multi.rb +5 -5
- data/lib/aspera/cli/main.rb +106 -48
- data/lib/aspera/cli/manager.rb +19 -20
- data/lib/aspera/cli/plugin.rb +22 -7
- data/lib/aspera/cli/plugins/aoc.rb +260 -208
- 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 +360 -189
- data/lib/aspera/cli/plugins/faspex.rb +119 -56
- data/lib/aspera/cli/plugins/faspex5.rb +32 -17
- data/lib/aspera/cli/plugins/node.rb +72 -31
- data/lib/aspera/cli/plugins/orchestrator.rb +5 -3
- data/lib/aspera/cli/plugins/preview.rb +94 -68
- data/lib/aspera/cli/plugins/server.rb +16 -5
- data/lib/aspera/cli/plugins/shares.rb +17 -0
- data/lib/aspera/cli/transfer_agent.rb +64 -82
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/command_line_builder.rb +48 -31
- data/lib/aspera/cos_node.rb +4 -3
- 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} +42 -38
- data/lib/aspera/fasp/{http_gw.rb → agent_httpgw.rb} +50 -29
- data/lib/aspera/fasp/{node.rb → agent_node.rb} +43 -4
- 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 +78 -91
- data/lib/aspera/fasp/parameters.yaml +531 -0
- data/lib/aspera/fasp/uri.rb +1 -1
- data/lib/aspera/faspex_gw.rb +12 -11
- data/lib/aspera/id_generator.rb +22 -0
- 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 +9 -4
- data/lib/aspera/oauth.rb +116 -100
- data/lib/aspera/persistency_action_once.rb +11 -7
- data/lib/aspera/persistency_folder.rb +6 -26
- data/lib/aspera/rest.rb +66 -50
- data/lib/aspera/sync.rb +40 -35
- data/lib/aspera/timer_limiter.rb +22 -0
- metadata +86 -29
- data/docs/transfer_spec.html +0 -99
- data/lib/aspera/api_detector.rb +0 -60
- data/lib/aspera/fasp/aoc.rb +0 -24
- data/lib/aspera/secrets.rb +0 -20
data/lib/aspera/cli/main.rb
CHANGED
@@ -4,82 +4,96 @@ 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'
|
23
|
+
# name of the containing gem, same as in <gem name>.gemspec
|
24
24
|
GEM_NAME = 'aspera-cli'
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
+
# store transfer result using this key and use result_transfer_multiple
|
29
|
+
STATUS_FIELD = 'status'
|
28
30
|
|
31
|
+
private_constant :PROGRAM_NAME,:GEM_NAME,:HELP_URL,:GEM_URL
|
29
32
|
# =============================================================
|
30
33
|
# Parameter handlers
|
31
34
|
#
|
32
|
-
|
33
|
-
def option_insecure; Rest.insecure ; end
|
34
|
-
|
35
|
-
def option_insecure=(value); Rest.insecure = value; end
|
36
|
-
|
35
|
+
attr_accessor :option_insecure, :option_http_options
|
37
36
|
def option_ui; OpenApplication.instance.url_method; end
|
38
37
|
|
39
38
|
def option_ui=(value); OpenApplication.instance.url_method=value; end
|
40
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
|
+
|
41
58
|
# minimum initialization
|
42
59
|
def initialize(argv)
|
43
|
-
# first thing : manage debug level (allows debugging
|
60
|
+
# first thing : manage debug level (allows debugging of option parser)
|
44
61
|
early_debug_setup(argv)
|
62
|
+
# compare $0 with expected name
|
45
63
|
current_prog_name=File.basename($PROGRAM_NAME)
|
46
64
|
unless current_prog_name.eql?(PROGRAM_NAME)
|
47
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")
|
48
66
|
end
|
49
|
-
# overriding parameters on transfer spec
|
50
67
|
@option_help=false
|
51
68
|
@bash_completion=false
|
52
69
|
@option_show_config=false
|
70
|
+
@option_insecure=false
|
71
|
+
@option_rest_debug=false
|
72
|
+
@option_http_options={}
|
73
|
+
# environment provided to plugin for various capabilities
|
53
74
|
@plugin_env={}
|
54
|
-
|
55
|
-
@
|
56
|
-
#
|
57
|
-
app_main_folder=ENV[conf_dir_env_var]
|
58
|
-
# if env var undefined or empty
|
59
|
-
if app_main_folder.nil? or app_main_folder.empty?
|
60
|
-
user_home_folder=Dir.home
|
61
|
-
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)
|
62
|
-
app_main_folder=File.join(user_home_folder,Plugins::Config::ASPERA_HOME_FOLDER_NAME,PROGRAM_NAME)
|
63
|
-
end
|
64
|
-
@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
|
65
78
|
@plugin_env[:formater]=Formater.new(@plugin_env[:options])
|
66
79
|
Rest.user_agent=PROGRAM_NAME
|
67
|
-
|
80
|
+
Rest.session_cb=lambda {|http| set_http_parameters(http)}
|
81
|
+
# declare and parse global options
|
68
82
|
init_global_options()
|
69
|
-
#
|
70
|
-
@plugin_env[:
|
71
|
-
# the Config plugin adds the @preset parser
|
72
|
-
@plugin_env[:config]=Plugins::Config.new(@plugin_env,PROGRAM_NAME,@help_url,Aspera::Cli::VERSION,app_main_folder)
|
83
|
+
# 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)
|
73
85
|
# the TransferAgent plugin may use the @preset parser
|
74
|
-
@plugin_env[:transfer]=TransferAgent.new(@plugin_env)
|
75
|
-
|
76
|
-
# set application folder for modules
|
86
|
+
@plugin_env[:transfer]=TransferAgent.new(@plugin_env[:options],@plugin_env[:config])
|
87
|
+
# data persistency
|
77
88
|
@plugin_env[:persistency]=PersistencyFolder.new(File.join(@plugin_env[:config].main_folder,'persist_store'))
|
89
|
+
Log.log.debug('plugin env created'.red)
|
78
90
|
Oauth.persist_mgr=@plugin_env[:persistency]
|
79
91
|
Fasp::Parameters.file_list_folder=File.join(@plugin_env[:config].main_folder,'filelists')
|
80
92
|
Aspera::RestErrorAnalyzer.instance.log_file=File.join(@plugin_env[:config].main_folder,'rest_exceptions.log')
|
81
93
|
# register aspera REST call error handlers
|
82
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
|
83
97
|
end
|
84
98
|
|
85
99
|
def app_banner
|
@@ -88,18 +102,19 @@ module Aspera
|
|
88
102
|
banner << "\t#{PROGRAM_NAME} COMMANDS [OPTIONS] [ARGS]\n"
|
89
103
|
banner << "\nDESCRIPTION\n"
|
90
104
|
banner << "\tUse Aspera application to perform operations on command line.\n"
|
91
|
-
banner << "\tDocumentation and examples: #{
|
105
|
+
banner << "\tDocumentation and examples: #{GEM_URL}\n"
|
92
106
|
banner << "\texecute: #{PROGRAM_NAME} conf doc\n"
|
93
|
-
banner << "\tor visit: #{
|
107
|
+
banner << "\tor visit: #{HELP_URL}\n"
|
108
|
+
banner << "\tsource repo: #{SRC_URL}\n"
|
94
109
|
banner << "\nENVIRONMENT VARIABLES\n"
|
95
110
|
banner << "\t#{conf_dir_env_var} config folder, default: $HOME/#{Plugins::Config::ASPERA_HOME_FOLDER_NAME}/#{PROGRAM_NAME}\n"
|
96
|
-
banner << "\
|
111
|
+
banner << "\tany option can be set as an environment variable, refer to the manual\n"
|
97
112
|
banner << "\nCOMMANDS\n"
|
98
113
|
banner << "\tTo list first level commands, execute: #{PROGRAM_NAME}\n"
|
99
114
|
banner << "\tNote that commands can be written shortened (provided it is unique).\n"
|
100
115
|
banner << "\nOPTIONS\n"
|
101
116
|
banner << "\tOptions begin with a '-' (minus), and value is provided on command line.\n"
|
102
|
-
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"
|
103
118
|
banner << "\tDates format is 'DD-MM-YY HH:MM:SS', or 'now' or '-<num>h'\n\n"
|
104
119
|
banner << "ARGS\n"
|
105
120
|
banner << "\tSome commands require mandatory arguments, e.g. a path.\n"
|
@@ -111,7 +126,7 @@ module Aspera
|
|
111
126
|
@opt_mgr.add_opt_switch(:help,"-h","Show this message.") { @option_help=true }
|
112
127
|
@opt_mgr.add_opt_switch(:bash_comp,"generate bash completion for command") { @bash_completion=true }
|
113
128
|
@opt_mgr.add_opt_switch(:show_config, "Display parameters used for the provided action.") { @option_show_config=true }
|
114
|
-
@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 }
|
115
130
|
@opt_mgr.add_opt_switch(:version,'-v','display version') { @plugin_env[:formater].display_message(:data,Aspera::Cli::VERSION);Process.exit(0) }
|
116
131
|
@opt_mgr.add_opt_switch(:warnings,'-w','check for language warnings') { $VERBOSE=true }
|
117
132
|
# handler must be set before declaration
|
@@ -119,13 +134,17 @@ module Aspera
|
|
119
134
|
@opt_mgr.set_obj_attr(:logger,Log.instance,:logger_type)
|
120
135
|
@opt_mgr.set_obj_attr(:insecure,self,:option_insecure,:no)
|
121
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)
|
122
139
|
@opt_mgr.add_opt_list(:ui,OpenApplication.user_interfaces,'method to start browser')
|
123
140
|
@opt_mgr.add_opt_list(:log_level,Log.levels,"Log level")
|
124
141
|
@opt_mgr.add_opt_list(:logger,Log.logtypes,"log method")
|
125
142
|
@opt_mgr.add_opt_simple(:lock_port,"prevent dual execution of a command, e.g. in cron")
|
126
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)")
|
127
145
|
@opt_mgr.add_opt_boolean(:insecure,"do not validate HTTPS certificate")
|
128
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")
|
129
148
|
@opt_mgr.set_option(:ui,OpenApplication.default_gui_mode)
|
130
149
|
@opt_mgr.set_option(:once_only,:false)
|
131
150
|
# parse declared options
|
@@ -141,7 +160,7 @@ module Aspera
|
|
141
160
|
require @plugin_env[:config].plugins[plugin_name_sym][:require_stanza]
|
142
161
|
# load default params only if no param already loaded before plugin instanciation
|
143
162
|
env[:config].add_plugin_default_preset(plugin_name_sym)
|
144
|
-
command_plugin=Plugins::Config.
|
163
|
+
command_plugin=Plugins::Config.plugin_class(plugin_name_sym).new(env)
|
145
164
|
Log.log.debug("got #{command_plugin.class}")
|
146
165
|
# TODO: check that ancestor is Plugin?
|
147
166
|
return command_plugin
|
@@ -177,10 +196,11 @@ module Aspera
|
|
177
196
|
# override main option parser with a brand new, to avoid having global options
|
178
197
|
plugin_env=@plugin_env.clone
|
179
198
|
plugin_env[:man_only]=true
|
180
|
-
plugin_env[:options]=Manager.new(PROGRAM_NAME
|
199
|
+
plugin_env[:options]=Manager.new(PROGRAM_NAME)
|
200
|
+
plugin_env[:options].parser.banner='' # remove default banner
|
181
201
|
get_plugin_instance_with_options(plugin_name_sym,plugin_env)
|
182
202
|
# display generated help for plugin options
|
183
|
-
@plugin_env[:formater].display_message(:error,plugin_env[:options].parser.
|
203
|
+
@plugin_env[:formater].display_message(:error,plugin_env[:options].parser.help)
|
184
204
|
end
|
185
205
|
end
|
186
206
|
Process.exit(0)
|
@@ -188,10 +208,24 @@ module Aspera
|
|
188
208
|
|
189
209
|
protected
|
190
210
|
|
211
|
+
# env var name to override the app's main folder
|
212
|
+
# default main folder is $HOME/<vendor main app folder>/<program name>
|
191
213
|
def conf_dir_env_var
|
192
214
|
return "#{PROGRAM_NAME}_home".upcase
|
193
215
|
end
|
194
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
|
+
|
195
229
|
# early debug for parser
|
196
230
|
# Note: does not accept shortcuts
|
197
231
|
def early_debug_setup(argv)
|
@@ -219,19 +253,35 @@ module Aspera
|
|
219
253
|
return Main.result_nothing
|
220
254
|
end
|
221
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
|
+
|
222
272
|
# this is the main function called by initial script just after constructor
|
223
273
|
def process_command_line
|
224
274
|
Log.log.debug('process_command_line')
|
275
|
+
# catch exception information , if any
|
225
276
|
exception_info=nil
|
277
|
+
# false if command shall not be executed ("once_only")
|
278
|
+
execute_command=true
|
226
279
|
begin
|
227
280
|
# find plugins, shall be after parse! ?
|
228
281
|
@plugin_env[:config].add_plugins_from_lookup_folders
|
229
282
|
# help requested without command ? (plugins must be known here)
|
230
283
|
exit_with_usage(true) if @option_help and @opt_mgr.command_or_arg_empty?
|
231
284
|
generate_bash_completion if @bash_completion
|
232
|
-
# load global default options and process
|
233
|
-
@plugin_env[:config].add_plugin_default_preset(Plugins::Config::CONF_GLOBAL_SYM)
|
234
|
-
@opt_mgr.parse_options!
|
235
285
|
@plugin_env[:config].periodic_check_newer_gem_version
|
236
286
|
if @option_show_config and @opt_mgr.command_or_arg_empty?
|
237
287
|
command_sym=Plugins::Config::CONF_PLUGIN_SYM
|
@@ -264,11 +314,12 @@ module Aspera
|
|
264
314
|
Log.log.debug("Opening lock port #{lock_port.to_i}")
|
265
315
|
@tcp_server=TCPServer.new('127.0.0.1',lock_port.to_i)
|
266
316
|
rescue => e
|
267
|
-
|
317
|
+
execute_command=false
|
318
|
+
Log.log.warn("Another instance is already running (#{e.message}).")
|
268
319
|
end
|
269
320
|
end
|
270
|
-
# execute and display
|
271
|
-
@plugin_env[:formater].display_results(command_plugin.execute_action)
|
321
|
+
# execute and display (if not exclusive execution)
|
322
|
+
@plugin_env[:formater].display_results(command_plugin.execute_action) if execute_command
|
272
323
|
# finish
|
273
324
|
@plugin_env[:transfer].shutdown
|
274
325
|
rescue CliBadArgument => e; exception_info=[e,'Argument',:usage]
|
@@ -286,10 +337,17 @@ module Aspera
|
|
286
337
|
unless exception_info.nil?
|
287
338
|
@plugin_env[:formater].display_message(:error,"ERROR:".bg_red.gray.blink+" "+exception_info[1]+": "+exception_info[0].message)
|
288
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}'")
|
342
|
+
end
|
289
343
|
end
|
290
344
|
# 2- processing of command not processed (due to exception or bad command line)
|
291
|
-
|
292
|
-
@
|
345
|
+
if execute_command
|
346
|
+
@opt_mgr.final_errors.each do |msg|
|
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?
|
350
|
+
end
|
293
351
|
end
|
294
352
|
# 3- in case of error, fail the process status
|
295
353
|
unless exception_info.nil?
|
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
@@ -2,10 +2,15 @@ module Aspera
|
|
2
2
|
module Cli
|
3
3
|
# base class for plugins modules
|
4
4
|
class Plugin
|
5
|
+
# operation without id
|
5
6
|
GLOBAL_OPS=[:create,:list]
|
7
|
+
# operation on specific instance
|
6
8
|
INSTANCE_OPS=[:modify,:delete,:show]
|
7
9
|
ALL_OPS=[GLOBAL_OPS,INSTANCE_OPS].flatten
|
8
|
-
#
|
10
|
+
# max number of items for list command
|
11
|
+
MAX_ITEMS='max'
|
12
|
+
# max number of pages for list command
|
13
|
+
MAX_PAGES='pmax'
|
9
14
|
|
10
15
|
@@done=false
|
11
16
|
|
@@ -28,10 +33,18 @@ module Aspera
|
|
28
33
|
end
|
29
34
|
end
|
30
35
|
|
31
|
-
|
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
|
+
|
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)
|
32
45
|
if INSTANCE_OPS.include?(command)
|
33
46
|
begin
|
34
|
-
one_res_id=
|
47
|
+
one_res_id=instance_identifier()
|
35
48
|
rescue => e
|
36
49
|
raise e if id_default.nil?
|
37
50
|
one_res_id=id_default
|
@@ -54,10 +67,11 @@ module Aspera
|
|
54
67
|
when :list
|
55
68
|
resp=rest_api.read(res_class_path,parameters)
|
56
69
|
data=resp[:data]
|
70
|
+
# TODO: not generic : which application is this for ?
|
57
71
|
if resp[:http]['Content-Type'].start_with?('application/vnd.api+json')
|
58
|
-
data=
|
72
|
+
data=data[res_class_path]
|
59
73
|
end
|
60
|
-
data=data[res_class_path] if
|
74
|
+
data=data[res_class_path] if use_subkey
|
61
75
|
return {:type => :object_list, :data=>data, :fields=>display_fields}
|
62
76
|
when :modify
|
63
77
|
property=self.options.get_option(:property,:optional)
|
@@ -74,12 +88,13 @@ module Aspera
|
|
74
88
|
end
|
75
89
|
|
76
90
|
# implement generic rest operations on given resource path
|
77
|
-
def entity_action(rest_api,res_class_path,display_fields,id_symb,id_default=nil,
|
91
|
+
def entity_action(rest_api,res_class_path,display_fields,id_symb,id_default=nil,use_subkey=false)
|
78
92
|
#res_name=res_class_path.gsub(%r{^.*/},'').gsub(%r{s$},'').gsub('_',' ')
|
79
93
|
command=self.options.get_next_command(ALL_OPS)
|
80
|
-
return entity_command(command,rest_api,res_class_path,display_fields,id_symb,id_default,
|
94
|
+
return entity_command(command,rest_api,res_class_path,display_fields,id_symb,id_default,use_subkey)
|
81
95
|
end
|
82
96
|
|
97
|
+
# shortcuts for plugin environment
|
83
98
|
def options; return @agents[:options];end
|
84
99
|
|
85
100
|
def transfer; return @agents[:transfer];end
|