aspera-cli 4.6.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 +427 -300
- data/bin/ascli +2 -1
- data/bin/asession +1 -0
- data/docs/test_env.conf +2 -0
- data/examples/aoc.rb +4 -3
- data/examples/faspex4.rb +21 -19
- data/examples/proxy.pac +1 -1
- data/examples/transfer.rb +15 -15
- data/lib/aspera/aoc.rb +135 -124
- data/lib/aspera/ascmd.rb +85 -75
- 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 +138 -111
- 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 +13 -16
- data/lib/aspera/cli/main.rb +122 -130
- data/lib/aspera/cli/manager.rb +146 -154
- data/lib/aspera/cli/plugin.rb +38 -34
- data/lib/aspera/cli/plugins/alee.rb +6 -6
- data/lib/aspera/cli/plugins/aoc.rb +273 -276
- data/lib/aspera/cli/plugins/ats.rb +82 -76
- data/lib/aspera/cli/plugins/bss.rb +14 -16
- data/lib/aspera/cli/plugins/config.rb +350 -306
- 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 +180 -159
- data/lib/aspera/cli/plugins/faspex5.rb +64 -54
- data/lib/aspera/cli/plugins/node.rb +147 -140
- data/lib/aspera/cli/plugins/orchestrator.rb +68 -66
- 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 +23 -24
- data/lib/aspera/cli/plugins/sync.rb +20 -22
- data/lib/aspera/cli/transfer_agent.rb +40 -39
- 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/agent_base.rb +22 -20
- data/lib/aspera/fasp/agent_connect.rb +13 -11
- data/lib/aspera/fasp/agent_direct.rb +48 -59
- data/lib/aspera/fasp/agent_httpgw.rb +33 -39
- data/lib/aspera/fasp/agent_node.rb +15 -13
- data/lib/aspera/fasp/agent_trsdk.rb +12 -14
- data/lib/aspera/fasp/error.rb +2 -1
- data/lib/aspera/fasp/error_info.rb +68 -52
- data/lib/aspera/fasp/installation.rb +106 -94
- data/lib/aspera/fasp/listener.rb +1 -0
- data/lib/aspera/fasp/parameters.rb +83 -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 -90
- data/lib/aspera/hash_ext.rb +4 -3
- data/lib/aspera/id_generator.rb +8 -7
- data/lib/aspera/keychain/encrypted_hash.rb +17 -16
- data/lib/aspera/keychain/macos_security.rb +6 -10
- data/lib/aspera/log.rb +25 -20
- data/lib/aspera/nagios.rb +13 -12
- data/lib/aspera/node.rb +30 -22
- 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 +115 -113
- 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 +64 -21
- data/docs/Makefile +0 -65
- data/docs/README.erb.md +0 -4424
- data/docs/README.md +0 -13
- data/docs/diagrams.txt +0 -49
- data/docs/doc_tools.rb +0 -58
- data/lib/aspera/cli/plugins/shares2.rb +0 -114
- data/lib/aspera/fasp/default.rb +0 -17
data/lib/aspera/cli/manager.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'aspera/colors'
|
|
2
3
|
require 'aspera/log'
|
|
3
4
|
require 'aspera/cli/extended_value'
|
|
@@ -29,11 +30,11 @@ module Aspera
|
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
def value
|
|
32
|
-
@object.send(@attr_symb
|
|
33
|
+
return @object.send(@attr_symb)
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
def value=(val)
|
|
36
|
-
@object.send(@attr_symb
|
|
37
|
+
@object.send("#{@attr_symb}=",val)
|
|
37
38
|
end
|
|
38
39
|
end
|
|
39
40
|
|
|
@@ -41,14 +42,10 @@ module Aspera
|
|
|
41
42
|
# arguments options start with '-', others are commands
|
|
42
43
|
# resolves on extended value syntax
|
|
43
44
|
class Manager
|
|
44
|
-
def self.time_to_string(time)
|
|
45
|
-
time.strftime("%Y-%m-%d %H:%M:%S")
|
|
46
|
-
end
|
|
47
|
-
|
|
48
45
|
# boolean options are set to true/false from the following values
|
|
49
|
-
TRUE_VALUES=[:yes,true]
|
|
50
|
-
BOOLEAN_VALUES=TRUE_VALUES
|
|
51
|
-
BOOLEAN_SIMPLE=[:yes,:no]
|
|
46
|
+
TRUE_VALUES=[:yes,true].freeze
|
|
47
|
+
BOOLEAN_VALUES=[TRUE_VALUES,:no,false].flatten.freeze
|
|
48
|
+
BOOLEAN_SIMPLE=[:yes,:no].freeze
|
|
52
49
|
# option name separator on command line
|
|
53
50
|
OPTION_SEP_LINE='-'
|
|
54
51
|
# option name separator in code (symbol)
|
|
@@ -56,30 +53,37 @@ module Aspera
|
|
|
56
53
|
|
|
57
54
|
private_constant :TRUE_VALUES,:BOOLEAN_VALUES,:BOOLEAN_SIMPLE,:OPTION_SEP_LINE,:OPTION_SEP_NAME
|
|
58
55
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
56
|
+
class << self
|
|
57
|
+
def enum_to_bool(enum)
|
|
58
|
+
raise "Value not valid for boolean: #{enum}/#{enum.class}" unless BOOLEAN_VALUES.include?(enum)
|
|
59
|
+
return TRUE_VALUES.include?(enum)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def time_to_string(time)
|
|
63
|
+
return time.strftime('%Y-%m-%d %H:%M:%S')
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# find shortened string value in allowed symbol list
|
|
67
|
+
def get_from_list(shortval,descr,allowed_values)
|
|
68
|
+
# we accept shortcuts
|
|
69
|
+
matching_exact=allowed_values.select{|i| i.to_s.eql?(shortval)}
|
|
70
|
+
return matching_exact.first if matching_exact.length == 1
|
|
71
|
+
matching=allowed_values.select{|i| i.to_s.start_with?(shortval)}
|
|
72
|
+
raise CliBadArgument,bad_arg_message_multi("unknown value for #{descr}: #{shortval}",allowed_values) if matching.empty?
|
|
73
|
+
raise CliBadArgument,bad_arg_message_multi("ambigous shortcut for #{descr}: #{shortval}",matching) unless matching.length.eql?(1)
|
|
74
|
+
return enum_to_bool(matching.first) if allowed_values.eql?(BOOLEAN_VALUES)
|
|
75
|
+
return matching.first
|
|
76
|
+
end
|
|
72
77
|
|
|
73
|
-
|
|
74
|
-
|
|
78
|
+
def bad_arg_message_multi(error_msg,choices)
|
|
79
|
+
return [error_msg,'Use:',choices.map{|c|"- #{c}"}.sort].flatten.join("\n")
|
|
80
|
+
end
|
|
75
81
|
end
|
|
76
82
|
|
|
77
83
|
attr_reader :parser
|
|
78
|
-
attr_accessor :ask_missing_mandatory
|
|
79
|
-
attr_accessor :ask_missing_optional
|
|
84
|
+
attr_accessor :ask_missing_mandatory, :ask_missing_optional
|
|
80
85
|
attr_writer :fail_on_missing_mandatory
|
|
81
86
|
|
|
82
|
-
#
|
|
83
87
|
def initialize(program_name,argv=nil)
|
|
84
88
|
# command line values not starting with '-'
|
|
85
89
|
@unprocessed_cmd_line_arguments=[]
|
|
@@ -114,15 +118,15 @@ module Aspera
|
|
|
114
118
|
unless argv.nil?
|
|
115
119
|
@parser.separator('')
|
|
116
120
|
@parser.separator('OPTIONS: global')
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
121
|
+
set_obj_attr(:interactive,self,:ask_missing_mandatory)
|
|
122
|
+
set_obj_attr(:ask_options,self,:ask_missing_optional)
|
|
123
|
+
add_opt_boolean(:interactive,'use interactive input of missing params')
|
|
124
|
+
add_opt_boolean(:ask_options,'ask even optional options')
|
|
125
|
+
parse_options!
|
|
122
126
|
process_options=true
|
|
123
127
|
while !argv.empty?
|
|
124
128
|
value=argv.shift
|
|
125
|
-
if process_options
|
|
129
|
+
if process_options && value.start_with?('-')
|
|
126
130
|
if value.eql?('--')
|
|
127
131
|
process_options=false
|
|
128
132
|
else
|
|
@@ -137,41 +141,6 @@ module Aspera
|
|
|
137
141
|
Log.log.debug("add_cmd_line_options:commands/args=#{@unprocessed_cmd_line_arguments},options=#{@unprocessed_cmd_line_options}".red)
|
|
138
142
|
end
|
|
139
143
|
|
|
140
|
-
def prompt_user_input(prompt,sensitive)
|
|
141
|
-
return STDIN.getpass("#{prompt}> ") if sensitive
|
|
142
|
-
print "#{prompt}> "
|
|
143
|
-
return STDIN.gets.chomp
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def get_interactive(type,descr,expected=:single)
|
|
147
|
-
if !@ask_missing_mandatory
|
|
148
|
-
if expected.is_a?(Array)
|
|
149
|
-
raise self.class.cli_bad_arg("missing: #{descr}",expected)
|
|
150
|
-
end
|
|
151
|
-
raise CliBadArgument,"missing argument (#{expected}): #{descr}"
|
|
152
|
-
end
|
|
153
|
-
result=nil
|
|
154
|
-
# Note: mandatory parenthesis here !
|
|
155
|
-
sensitive = (type.eql?(:option) and @declared_options[descr.to_sym][:sensitive].eql?(true))
|
|
156
|
-
default_prompt="#{type}: #{descr}"
|
|
157
|
-
# ask interactively
|
|
158
|
-
case expected
|
|
159
|
-
when :multiple
|
|
160
|
-
result=[]
|
|
161
|
-
puts " (one per line, end with empty line)"
|
|
162
|
-
loop do
|
|
163
|
-
entry=prompt_user_input(default_prompt,sensitive)
|
|
164
|
-
break if entry.empty?
|
|
165
|
-
result.push(ExtendedValue.instance.evaluate(entry))
|
|
166
|
-
end
|
|
167
|
-
when :single
|
|
168
|
-
result=ExtendedValue.instance.evaluate(prompt_user_input(default_prompt,sensitive))
|
|
169
|
-
else # one fixed
|
|
170
|
-
result=self.class.get_from_list(prompt_user_input("#{expected.join(' ')}\n#{default_prompt}",sensitive),descr,expected)
|
|
171
|
-
end
|
|
172
|
-
return result
|
|
173
|
-
end
|
|
174
|
-
|
|
175
144
|
def get_next_command(command_list); return get_next_argument('command',command_list); end
|
|
176
145
|
|
|
177
146
|
# @param expected is
|
|
@@ -190,17 +159,15 @@ module Aspera
|
|
|
190
159
|
when :multiple
|
|
191
160
|
result = @unprocessed_cmd_line_arguments.shift(@unprocessed_cmd_line_arguments.length).map{|v|ExtendedValue.instance.evaluate(v)}
|
|
192
161
|
# if expecting list and only one arg of type array : it is the list
|
|
193
|
-
if result.length.eql?(1)
|
|
162
|
+
if result.length.eql?(1) && result.first.is_a?(Array)
|
|
194
163
|
result=result.first
|
|
195
164
|
end
|
|
196
165
|
else
|
|
197
166
|
result=self.class.get_from_list(@unprocessed_cmd_line_arguments.shift,descr,expected)
|
|
198
167
|
end
|
|
199
|
-
|
|
168
|
+
elsif is_type.eql?(:mandatory)
|
|
200
169
|
# no value provided
|
|
201
|
-
|
|
202
|
-
result=get_interactive(:argument,descr,expected)
|
|
203
|
-
end
|
|
170
|
+
result=get_interactive(:argument,descr,expected)
|
|
204
171
|
end
|
|
205
172
|
Log.log.debug("#{descr}=#{result}")
|
|
206
173
|
return result
|
|
@@ -213,13 +180,9 @@ module Aspera
|
|
|
213
180
|
raise "INTERNAL ERROR: option #{option_symbol} already declared. only accessor can be redeclared and ignored" unless @declared_options[option_symbol][:type].eql?(:accessor)
|
|
214
181
|
return
|
|
215
182
|
end
|
|
216
|
-
@declared_options[option_symbol]={:type
|
|
183
|
+
@declared_options[option_symbol]={type: type}
|
|
217
184
|
# by default passwords and secrets are sensitive, else specify when declaring the option
|
|
218
|
-
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
def set_is_sensitive(option_symbol)
|
|
222
|
-
@declared_options[option_symbol][:sensitive]=true
|
|
185
|
+
@declared_options[option_symbol][:sensitive]=true if !%w[password secret key].select{|i| option_symbol.to_s.end_with?(i)}.empty?
|
|
223
186
|
end
|
|
224
187
|
|
|
225
188
|
# define option with handler
|
|
@@ -227,29 +190,26 @@ module Aspera
|
|
|
227
190
|
Log.log.debug("set attr obj #{option_symbol} (#{object},#{attr_symb})")
|
|
228
191
|
declare_option(option_symbol,:accessor)
|
|
229
192
|
@declared_options[option_symbol][:accessor]=AttrAccessor.new(object,attr_symb)
|
|
230
|
-
set_option(option_symbol,default_value,
|
|
193
|
+
set_option(option_symbol,default_value,'default obj attr') if !default_value.nil?
|
|
231
194
|
end
|
|
232
195
|
|
|
233
196
|
# set an option value by name, either store value or call handler
|
|
234
|
-
def set_option(option_symbol,value,where=
|
|
235
|
-
if
|
|
197
|
+
def set_option(option_symbol,value,where='default')
|
|
198
|
+
if !@declared_options.has_key?(option_symbol)
|
|
236
199
|
Log.log.debug("set unknown option: #{option_symbol}")
|
|
237
|
-
raise
|
|
200
|
+
raise 'ERROR: cannot set undeclared option'
|
|
238
201
|
#declare_option(option_symbol)
|
|
239
202
|
end
|
|
240
203
|
value=ExtendedValue.instance.evaluate(value)
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
value=enum_to_bool(value)
|
|
244
|
-
end
|
|
245
|
-
Log.log.debug("set #{option_symbol}=#{value} (#{@declared_options[option_symbol][:type]}) : #{where}".blue)
|
|
204
|
+
value=Manager.enum_to_bool(value) if @declared_options[option_symbol][:values].eql?(BOOLEAN_VALUES)
|
|
205
|
+
Log.log.debug("set #{option_symbol}=#{value} (#{@declared_options[option_symbol][:type]}) : #{where}")
|
|
246
206
|
case @declared_options[option_symbol][:type]
|
|
247
207
|
when :accessor
|
|
248
208
|
@declared_options[option_symbol][:accessor].value=value
|
|
249
209
|
when :value
|
|
250
210
|
@declared_options[option_symbol][:value]=value
|
|
251
211
|
else # nil or other
|
|
252
|
-
raise
|
|
212
|
+
raise 'error'
|
|
253
213
|
end
|
|
254
214
|
end
|
|
255
215
|
|
|
@@ -265,28 +225,25 @@ module Aspera
|
|
|
265
225
|
when :value
|
|
266
226
|
result=@declared_options[option_symbol][:value]
|
|
267
227
|
else
|
|
268
|
-
raise
|
|
228
|
+
raise 'unknown type'
|
|
269
229
|
end
|
|
270
230
|
Log.log.debug("get #{option_symbol} (#{@declared_options[option_symbol][:type]}) : #{result}")
|
|
271
231
|
end
|
|
272
232
|
# do not fail for manual generation if option mandatory but not set
|
|
273
|
-
result
|
|
274
|
-
Log.log.debug("interactive=#{@ask_missing_mandatory}")
|
|
233
|
+
result='' if result.nil? && !@fail_on_missing_mandatory
|
|
234
|
+
#Log.log.debug("interactive=#{@ask_missing_mandatory}")
|
|
275
235
|
if result.nil?
|
|
276
236
|
if !@ask_missing_mandatory
|
|
277
|
-
if is_type.eql?(:mandatory)
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
if @declared_options.has_key?(option_symbol) and @declared_options[option_symbol].has_key?(:values)
|
|
285
|
-
expected=@declared_options[option_symbol][:values]
|
|
286
|
-
end
|
|
287
|
-
result=get_interactive(:option,option_symbol.to_s,expected)
|
|
288
|
-
set_option(option_symbol,result,"interactive")
|
|
237
|
+
raise CliBadArgument,"Missing mandatory option: #{option_symbol}" if is_type.eql?(:mandatory)
|
|
238
|
+
elsif @ask_missing_optional || is_type.eql?(:mandatory)
|
|
239
|
+
# ask_missing_mandatory
|
|
240
|
+
expected=:single
|
|
241
|
+
#print "please enter: #{option_symbol.to_s}"
|
|
242
|
+
if @declared_options.has_key?(option_symbol) && @declared_options[option_symbol].has_key?(:values)
|
|
243
|
+
expected=@declared_options[option_symbol][:values]
|
|
289
244
|
end
|
|
245
|
+
result=get_interactive(:option,option_symbol.to_s,expected)
|
|
246
|
+
set_option(option_symbol,result,'interactive')
|
|
290
247
|
end
|
|
291
248
|
end
|
|
292
249
|
return result
|
|
@@ -300,17 +257,6 @@ module Aspera
|
|
|
300
257
|
preset_hash.each{|k,v|@unprocessed_defaults.send(op,[k.to_sym,v])}
|
|
301
258
|
end
|
|
302
259
|
|
|
303
|
-
# generate command line option from option symbol
|
|
304
|
-
def symbol_to_option(symbol,opt_val)
|
|
305
|
-
result='--'+symbol.to_s.gsub(OPTION_SEP_NAME,OPTION_SEP_LINE)
|
|
306
|
-
result=result+'='+opt_val unless opt_val.nil?
|
|
307
|
-
return result
|
|
308
|
-
end
|
|
309
|
-
|
|
310
|
-
def highlight_current(value)
|
|
311
|
-
STDOUT.isatty ? value.to_s.red.bold : "[#{value}]"
|
|
312
|
-
end
|
|
313
|
-
|
|
314
260
|
# define an option with restricted values
|
|
315
261
|
def add_opt_list(option_symbol,values,help,*on_args)
|
|
316
262
|
declare_option(option_symbol,:value)
|
|
@@ -321,12 +267,12 @@ module Aspera
|
|
|
321
267
|
value=get_option(option_symbol)
|
|
322
268
|
help_values=values.map{|i|i.eql?(value)?highlight_current(i):i}.join(', ')
|
|
323
269
|
if values.eql?(BOOLEAN_VALUES)
|
|
324
|
-
help_values=BOOLEAN_SIMPLE.map{|i|(
|
|
270
|
+
help_values=BOOLEAN_SIMPLE.map{|i|(i.eql?(:yes) && value) || (i.eql?(:no) && !value) ? highlight_current(i) : i}.join(', ')
|
|
325
271
|
end
|
|
326
272
|
on_args.push(values)
|
|
327
273
|
on_args.push("#{help}: #{help_values}")
|
|
328
274
|
Log.log.debug("on_args=#{on_args}")
|
|
329
|
-
@parser.on(*on_args){|v|set_option(option_symbol,self.class.get_from_list(v.to_s,help,values),
|
|
275
|
+
@parser.on(*on_args){|v|set_option(option_symbol,self.class.get_from_list(v.to_s,help,values),'cmdline')}
|
|
330
276
|
end
|
|
331
277
|
|
|
332
278
|
def add_opt_boolean(option_symbol,help,*on_args)
|
|
@@ -337,22 +283,22 @@ module Aspera
|
|
|
337
283
|
def add_opt_simple(option_symbol,*on_args)
|
|
338
284
|
declare_option(option_symbol,:value)
|
|
339
285
|
Log.log.debug("add_opt_simple #{option_symbol}")
|
|
340
|
-
on_args.unshift(symbol_to_option(option_symbol,
|
|
286
|
+
on_args.unshift(symbol_to_option(option_symbol,'VALUE'))
|
|
341
287
|
Log.log.debug("on_args=#{on_args}")
|
|
342
|
-
@parser.on(*on_args) { |v| set_option(option_symbol,v,
|
|
288
|
+
@parser.on(*on_args) { |v| set_option(option_symbol,v,'cmdline') }
|
|
343
289
|
end
|
|
344
290
|
|
|
345
291
|
# define an option with date format
|
|
346
292
|
def add_opt_date(option_symbol,*on_args)
|
|
347
293
|
declare_option(option_symbol,:value)
|
|
348
294
|
Log.log.debug("add_opt_date #{option_symbol}")
|
|
349
|
-
on_args.unshift(symbol_to_option(option_symbol,
|
|
295
|
+
on_args.unshift(symbol_to_option(option_symbol,'DATE'))
|
|
350
296
|
Log.log.debug("on_args=#{on_args}")
|
|
351
297
|
@parser.on(*on_args) do |v|
|
|
352
298
|
case v
|
|
353
|
-
when 'now'
|
|
354
|
-
when /^-([0-9]+)h
|
|
355
|
-
else set_option(option_symbol,v,
|
|
299
|
+
when 'now' then set_option(option_symbol,Manager.time_to_string(Time.now),'cmdline')
|
|
300
|
+
when /^-([0-9]+)h/ then set_option(option_symbol,Manager.time_to_string(Time.now-(3600*Regexp.last_match(1).to_i)),'cmdline')
|
|
301
|
+
else set_option(option_symbol,v,'cmdline')
|
|
356
302
|
end
|
|
357
303
|
end
|
|
358
304
|
end
|
|
@@ -379,15 +325,15 @@ module Aspera
|
|
|
379
325
|
end
|
|
380
326
|
|
|
381
327
|
# get all original options on command line used to generate a config in config file
|
|
382
|
-
def get_options_table(remove_from_remaining
|
|
328
|
+
def get_options_table(remove_from_remaining: true)
|
|
383
329
|
result={}
|
|
384
330
|
@initial_cli_options.each do |optionval|
|
|
385
331
|
case optionval
|
|
386
332
|
when /^--([^=]+)$/
|
|
387
333
|
# ignore
|
|
388
334
|
when /^--([^=]+)=(.*)$/
|
|
389
|
-
name
|
|
390
|
-
value
|
|
335
|
+
name=Regexp.last_match(1)
|
|
336
|
+
value=Regexp.last_match(2)
|
|
391
337
|
name.gsub!(OPTION_SEP_LINE,OPTION_SEP_NAME)
|
|
392
338
|
value=ExtendedValue.instance.evaluate(value)
|
|
393
339
|
Log.log.debug("option #{name}=#{value}")
|
|
@@ -401,46 +347,28 @@ module Aspera
|
|
|
401
347
|
end
|
|
402
348
|
|
|
403
349
|
# return options as taken from config file and command line just before command execution
|
|
404
|
-
def declared_options(
|
|
405
|
-
|
|
350
|
+
def declared_options(only_defined: false)
|
|
351
|
+
result={}
|
|
352
|
+
@declared_options.keys.each do |option_symb|
|
|
406
353
|
v=get_option(option_symb)
|
|
407
|
-
|
|
408
|
-
h
|
|
354
|
+
result[option_symb.to_s]=v unless only_defined && v.nil?
|
|
409
355
|
end
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
def apply_options_preset(preset,where,force=false)
|
|
413
|
-
unprocessed=[]
|
|
414
|
-
preset.each do |pair|
|
|
415
|
-
k,v=*pair
|
|
416
|
-
if @declared_options.has_key?(k)
|
|
417
|
-
# constrained parameters as string are revert to symbol
|
|
418
|
-
if @declared_options[k].has_key?(:values) and v.is_a?(String)
|
|
419
|
-
v=self.class.get_from_list(v,k.to_s+" in #{where}",@declared_options[k][:values])
|
|
420
|
-
end
|
|
421
|
-
set_option(k,v,where)
|
|
422
|
-
else
|
|
423
|
-
unprocessed.push(pair)
|
|
424
|
-
end
|
|
425
|
-
end
|
|
426
|
-
# keep only unprocessed values for next parse
|
|
427
|
-
preset.clear
|
|
428
|
-
preset.push(*unprocessed)
|
|
356
|
+
return result
|
|
429
357
|
end
|
|
430
358
|
|
|
431
359
|
# removes already known options from the list
|
|
432
360
|
def parse_options!
|
|
433
|
-
Log.log.debug(
|
|
361
|
+
Log.log.debug('parse_options!'.red)
|
|
434
362
|
# first conf file, then env var
|
|
435
|
-
apply_options_preset(@unprocessed_defaults,
|
|
436
|
-
apply_options_preset(@unprocessed_env,
|
|
363
|
+
apply_options_preset(@unprocessed_defaults,'file')
|
|
364
|
+
apply_options_preset(@unprocessed_env,'env')
|
|
437
365
|
# command line override
|
|
438
366
|
unknown_options=[]
|
|
439
367
|
begin
|
|
440
368
|
# remove known options one by one, exception if unknown
|
|
441
|
-
Log.log.debug(
|
|
369
|
+
Log.log.debug('before parse'.red)
|
|
442
370
|
@parser.parse!(@unprocessed_cmd_line_options)
|
|
443
|
-
Log.log.debug(
|
|
371
|
+
Log.log.debug('After parse'.red)
|
|
444
372
|
rescue OptionParser::InvalidOption => e
|
|
445
373
|
Log.log.debug("InvalidOption #{e}".red)
|
|
446
374
|
# save for later processing
|
|
@@ -451,6 +379,70 @@ module Aspera
|
|
|
451
379
|
# set unprocessed options for next time
|
|
452
380
|
@unprocessed_cmd_line_options=unknown_options
|
|
453
381
|
end
|
|
382
|
+
|
|
383
|
+
private
|
|
384
|
+
|
|
385
|
+
def prompt_user_input(prompt,sensitive)
|
|
386
|
+
return $stdin.getpass("#{prompt}> ") if sensitive
|
|
387
|
+
print "#{prompt}> "
|
|
388
|
+
return $stdin.gets.chomp
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def get_interactive(type,descr,expected=:single)
|
|
392
|
+
if !@ask_missing_mandatory
|
|
393
|
+
raise CliBadArgument,self.class.bad_arg_message_multi("missing: #{descr}",expected) if expected.is_a?(Array)
|
|
394
|
+
raise CliBadArgument,"missing argument (#{expected}): #{descr}"
|
|
395
|
+
end
|
|
396
|
+
result=nil
|
|
397
|
+
sensitive = type.eql?(:option) && @declared_options[descr.to_sym][:sensitive]
|
|
398
|
+
default_prompt="#{type}: #{descr}"
|
|
399
|
+
# ask interactively
|
|
400
|
+
case expected
|
|
401
|
+
when :multiple
|
|
402
|
+
result=[]
|
|
403
|
+
puts(' (one per line, end with empty line)')
|
|
404
|
+
loop do
|
|
405
|
+
entry=prompt_user_input(default_prompt,sensitive)
|
|
406
|
+
break if entry.empty?
|
|
407
|
+
result.push(ExtendedValue.instance.evaluate(entry))
|
|
408
|
+
end
|
|
409
|
+
when :single
|
|
410
|
+
result=ExtendedValue.instance.evaluate(prompt_user_input(default_prompt,sensitive))
|
|
411
|
+
else # one fixed
|
|
412
|
+
result=self.class.get_from_list(prompt_user_input("#{expected.join(' ')}\n#{default_prompt}",sensitive),descr,expected)
|
|
413
|
+
end
|
|
414
|
+
return result
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
# generate command line option from option symbol
|
|
418
|
+
def symbol_to_option(symbol,opt_val)
|
|
419
|
+
result='--'+symbol.to_s.gsub(OPTION_SEP_NAME,OPTION_SEP_LINE)
|
|
420
|
+
result=result+'='+opt_val unless opt_val.nil?
|
|
421
|
+
return result
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
def highlight_current(value)
|
|
425
|
+
$stdout.isatty ? value.to_s.red.bold : "[#{value}]"
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
def apply_options_preset(preset,where)
|
|
429
|
+
unprocessed=[]
|
|
430
|
+
preset.each do |pair|
|
|
431
|
+
k,v=*pair
|
|
432
|
+
if @declared_options.has_key?(k)
|
|
433
|
+
# constrained parameters as string are revert to symbol
|
|
434
|
+
if @declared_options[k].has_key?(:values) && v.is_a?(String)
|
|
435
|
+
v=self.class.get_from_list(v,k.to_s+" in #{where}",@declared_options[k][:values])
|
|
436
|
+
end
|
|
437
|
+
set_option(k,v,where)
|
|
438
|
+
else
|
|
439
|
+
unprocessed.push(pair)
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
# keep only unprocessed values for next parse
|
|
443
|
+
preset.clear
|
|
444
|
+
preset.push(*unprocessed)
|
|
445
|
+
end
|
|
454
446
|
end
|
|
455
447
|
end
|
|
456
448
|
end
|
data/lib/aspera/cli/plugin.rb
CHANGED
|
@@ -1,51 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Aspera
|
|
2
3
|
module Cli
|
|
3
4
|
# base class for plugins modules
|
|
4
5
|
class Plugin
|
|
5
6
|
# operation without id
|
|
6
|
-
GLOBAL_OPS=[:create,:list]
|
|
7
|
+
GLOBAL_OPS=[:create,:list].freeze
|
|
7
8
|
# operation on specific instance
|
|
8
|
-
INSTANCE_OPS=[:modify,:delete,:show]
|
|
9
|
-
ALL_OPS=[GLOBAL_OPS,INSTANCE_OPS].flatten
|
|
9
|
+
INSTANCE_OPS=[:modify,:delete,:show].freeze
|
|
10
|
+
ALL_OPS=[GLOBAL_OPS,INSTANCE_OPS].flatten.freeze
|
|
10
11
|
# max number of items for list command
|
|
11
12
|
MAX_ITEMS='max'
|
|
12
13
|
# max number of pages for list command
|
|
13
14
|
MAX_PAGES='pmax'
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
# global for inherited classes
|
|
17
|
+
@@options_created=false # rubocop:disable Style/ClassVars
|
|
16
18
|
|
|
17
19
|
def initialize(env)
|
|
18
20
|
@agents=env
|
|
19
21
|
raise StandardError,"execute_action shall be redefined by subclass #{self.class}" unless respond_to?(:execute_action)
|
|
20
|
-
raise StandardError,
|
|
22
|
+
raise StandardError,'ACTIONS shall be redefined by subclass' unless self.class.constants.include?(:ACTIONS)
|
|
21
23
|
unless env[:skip_option_header]
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
end
|
|
27
|
-
unless @@done
|
|
28
|
-
self.options.add_opt_simple(:value,"extended value for create, update, list filter")
|
|
29
|
-
self.options.add_opt_simple(:property,"name of property to set")
|
|
30
|
-
self.options.add_opt_simple(:id,"resource identifier (#{INSTANCE_OPS.join(",")})")
|
|
31
|
-
self.options.parse_options!
|
|
32
|
-
@@done=true
|
|
24
|
+
options.parser.separator ''
|
|
25
|
+
options.parser.separator "COMMAND: #{self.class.name.split('::').last.downcase}"
|
|
26
|
+
options.parser.separator "SUBCOMMANDS: #{self.class.const_get(:ACTIONS).map(&:to_s).join(' ')}"
|
|
27
|
+
options.parser.separator 'OPTIONS:'
|
|
33
28
|
end
|
|
29
|
+
return if @@options_created
|
|
30
|
+
options.add_opt_simple(:value,'extended value for create, update, list filter')
|
|
31
|
+
options.add_opt_simple(:property,'name of property to set')
|
|
32
|
+
options.add_opt_simple(:id,"resource identifier (#{INSTANCE_OPS.join(',')})")
|
|
33
|
+
options.parse_options!
|
|
34
|
+
@@options_created=true # rubocop:disable Style/ClassVars
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
# must be called AFTER the instance action
|
|
37
|
-
def instance_identifier
|
|
38
|
-
res_id=
|
|
39
|
-
res_id=
|
|
38
|
+
def instance_identifier
|
|
39
|
+
res_id=options.get_option(:id)
|
|
40
|
+
res_id=options.get_next_argument('identifier') if res_id.nil?
|
|
40
41
|
return res_id
|
|
41
42
|
end
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
# @param command [Symbol] command to execute: create show list modify delete
|
|
45
|
+
# @param rest_api [Rest] api to use
|
|
46
|
+
# @param res_class_path [String] sub path in URL to resource relative to base url
|
|
47
|
+
# @param display_fields [Array] fields to display by default
|
|
48
|
+
# @param id_default [String] default identifier to use for existing entity commands (show, modify)
|
|
49
|
+
# @param use_subkey [bool] true if the result is in a subkey of the json
|
|
50
|
+
def entity_command(command,rest_api,res_class_path,display_fields: nil,id_default: nil,use_subkey: false)
|
|
45
51
|
if INSTANCE_OPS.include?(command)
|
|
46
52
|
begin
|
|
47
53
|
one_res_id=instance_identifier()
|
|
48
|
-
rescue => e
|
|
54
|
+
rescue StandardError => e
|
|
49
55
|
raise e if id_default.nil?
|
|
50
56
|
one_res_id=id_default
|
|
51
57
|
end
|
|
@@ -53,17 +59,17 @@ module Aspera
|
|
|
53
59
|
end
|
|
54
60
|
# parameters mandatory for create/modify
|
|
55
61
|
if [:create,:modify].include?(command)
|
|
56
|
-
parameters=
|
|
62
|
+
parameters=options.get_option(:value,:mandatory)
|
|
57
63
|
end
|
|
58
64
|
# parameters optional for list
|
|
59
65
|
if [:list].include?(command)
|
|
60
|
-
parameters=
|
|
66
|
+
parameters=options.get_option(:value,:optional)
|
|
61
67
|
end
|
|
62
68
|
case command
|
|
63
69
|
when :create
|
|
64
|
-
return {:
|
|
70
|
+
return {type: :single_object, data: rest_api.create(res_class_path,parameters)[:data], fields: display_fields}
|
|
65
71
|
when :show
|
|
66
|
-
return {:
|
|
72
|
+
return {type: :single_object, data: rest_api.read(one_res_path)[:data], fields: display_fields}
|
|
67
73
|
when :list
|
|
68
74
|
resp=rest_api.read(res_class_path,parameters)
|
|
69
75
|
data=resp[:data]
|
|
@@ -72,26 +78,25 @@ module Aspera
|
|
|
72
78
|
data=data[res_class_path]
|
|
73
79
|
end
|
|
74
80
|
data=data[res_class_path] if use_subkey
|
|
75
|
-
return {:
|
|
81
|
+
return {type: :object_list, data: data, fields: display_fields}
|
|
76
82
|
when :modify
|
|
77
|
-
property=
|
|
83
|
+
property=options.get_option(:property,:optional)
|
|
78
84
|
parameters={property => parameters} unless property.nil?
|
|
79
85
|
rest_api.update(one_res_path,parameters)
|
|
80
86
|
return Main.result_status('modified')
|
|
81
87
|
when :delete
|
|
82
88
|
rest_api.delete(one_res_path)
|
|
83
|
-
return Main.result_status(
|
|
89
|
+
return Main.result_status('deleted')
|
|
84
90
|
else
|
|
85
91
|
raise "unknown action: #{command}"
|
|
86
92
|
end
|
|
87
|
-
raise "internal error should not reach here"
|
|
88
93
|
end
|
|
89
94
|
|
|
90
95
|
# implement generic rest operations on given resource path
|
|
91
|
-
def entity_action(rest_api,res_class_path
|
|
96
|
+
def entity_action(rest_api,res_class_path,**opts)
|
|
92
97
|
#res_name=res_class_path.gsub(%r{^.*/},'').gsub(%r{s$},'').gsub('_',' ')
|
|
93
|
-
command=
|
|
94
|
-
return entity_command(command,rest_api,res_class_path
|
|
98
|
+
command=options.get_next_command(ALL_OPS)
|
|
99
|
+
return entity_command(command,rest_api,res_class_path,**opts)
|
|
95
100
|
end
|
|
96
101
|
|
|
97
102
|
# shortcuts for plugin environment
|
|
@@ -104,7 +109,6 @@ module Aspera
|
|
|
104
109
|
def format; return @agents[:formater];end
|
|
105
110
|
|
|
106
111
|
def persistency; return @agents[:persistency];end
|
|
107
|
-
|
|
108
112
|
end # Plugin
|
|
109
113
|
end # Cli
|
|
110
114
|
end # Aspera
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'aspera/rest'
|
|
2
3
|
require 'aspera/aoc'
|
|
3
4
|
|
|
@@ -5,17 +6,16 @@ module Aspera
|
|
|
5
6
|
module Cli
|
|
6
7
|
module Plugins
|
|
7
8
|
class Alee < BasicAuthPlugin
|
|
8
|
-
|
|
9
|
-
ACTIONS=[ :entitlement ]
|
|
9
|
+
ACTIONS=[:entitlement]
|
|
10
10
|
|
|
11
11
|
def execute_action
|
|
12
|
-
command=
|
|
12
|
+
command=options.get_next_command(ACTIONS)
|
|
13
13
|
case command
|
|
14
14
|
when :entitlement
|
|
15
|
-
entitlement_id =
|
|
16
|
-
customer_id =
|
|
15
|
+
entitlement_id = options.get_option(:username,:mandatory)
|
|
16
|
+
customer_id = options.get_option(:password,:mandatory)
|
|
17
17
|
api_metering=AoC.metering_api(entitlement_id,customer_id)
|
|
18
|
-
return {:
|
|
18
|
+
return {type: :single_object, data: api_metering.read('entitlement')[:data]}
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
end # Aspera
|