aspera-cli 4.2.1 → 4.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|