aspera-cli 4.6.0 → 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +427 -300
  3. data/bin/ascli +2 -1
  4. data/bin/asession +1 -0
  5. data/docs/test_env.conf +2 -0
  6. data/examples/aoc.rb +4 -3
  7. data/examples/faspex4.rb +21 -19
  8. data/examples/proxy.pac +1 -1
  9. data/examples/transfer.rb +15 -15
  10. data/lib/aspera/aoc.rb +135 -124
  11. data/lib/aspera/ascmd.rb +85 -75
  12. data/lib/aspera/ats_api.rb +11 -10
  13. data/lib/aspera/cli/basic_auth_plugin.rb +13 -14
  14. data/lib/aspera/cli/extended_value.rb +42 -33
  15. data/lib/aspera/cli/formater.rb +138 -111
  16. data/lib/aspera/cli/info.rb +17 -0
  17. data/lib/aspera/cli/listener/line_dump.rb +3 -2
  18. data/lib/aspera/cli/listener/logger.rb +2 -1
  19. data/lib/aspera/cli/listener/progress.rb +16 -18
  20. data/lib/aspera/cli/listener/progress_multi.rb +13 -16
  21. data/lib/aspera/cli/main.rb +122 -130
  22. data/lib/aspera/cli/manager.rb +146 -154
  23. data/lib/aspera/cli/plugin.rb +38 -34
  24. data/lib/aspera/cli/plugins/alee.rb +6 -6
  25. data/lib/aspera/cli/plugins/aoc.rb +273 -276
  26. data/lib/aspera/cli/plugins/ats.rb +82 -76
  27. data/lib/aspera/cli/plugins/bss.rb +14 -16
  28. data/lib/aspera/cli/plugins/config.rb +350 -306
  29. data/lib/aspera/cli/plugins/console.rb +23 -19
  30. data/lib/aspera/cli/plugins/cos.rb +18 -18
  31. data/lib/aspera/cli/plugins/faspex.rb +180 -159
  32. data/lib/aspera/cli/plugins/faspex5.rb +64 -54
  33. data/lib/aspera/cli/plugins/node.rb +147 -140
  34. data/lib/aspera/cli/plugins/orchestrator.rb +68 -66
  35. data/lib/aspera/cli/plugins/preview.rb +92 -96
  36. data/lib/aspera/cli/plugins/server.rb +79 -75
  37. data/lib/aspera/cli/plugins/shares.rb +23 -24
  38. data/lib/aspera/cli/plugins/sync.rb +20 -22
  39. data/lib/aspera/cli/transfer_agent.rb +40 -39
  40. data/lib/aspera/cli/version.rb +2 -1
  41. data/lib/aspera/colors.rb +35 -27
  42. data/lib/aspera/command_line_builder.rb +48 -34
  43. data/lib/aspera/cos_node.rb +29 -21
  44. data/lib/aspera/data_repository.rb +3 -2
  45. data/lib/aspera/environment.rb +50 -45
  46. data/lib/aspera/fasp/agent_base.rb +22 -20
  47. data/lib/aspera/fasp/agent_connect.rb +13 -11
  48. data/lib/aspera/fasp/agent_direct.rb +48 -59
  49. data/lib/aspera/fasp/agent_httpgw.rb +33 -39
  50. data/lib/aspera/fasp/agent_node.rb +15 -13
  51. data/lib/aspera/fasp/agent_trsdk.rb +12 -14
  52. data/lib/aspera/fasp/error.rb +2 -1
  53. data/lib/aspera/fasp/error_info.rb +68 -52
  54. data/lib/aspera/fasp/installation.rb +106 -94
  55. data/lib/aspera/fasp/listener.rb +1 -0
  56. data/lib/aspera/fasp/parameters.rb +83 -92
  57. data/lib/aspera/fasp/parameters.yaml +305 -249
  58. data/lib/aspera/fasp/resume_policy.rb +11 -14
  59. data/lib/aspera/fasp/transfer_spec.rb +26 -0
  60. data/lib/aspera/fasp/uri.rb +22 -21
  61. data/lib/aspera/faspex_gw.rb +55 -90
  62. data/lib/aspera/hash_ext.rb +4 -3
  63. data/lib/aspera/id_generator.rb +8 -7
  64. data/lib/aspera/keychain/encrypted_hash.rb +17 -16
  65. data/lib/aspera/keychain/macos_security.rb +6 -10
  66. data/lib/aspera/log.rb +25 -20
  67. data/lib/aspera/nagios.rb +13 -12
  68. data/lib/aspera/node.rb +30 -22
  69. data/lib/aspera/oauth.rb +175 -226
  70. data/lib/aspera/open_application.rb +4 -3
  71. data/lib/aspera/persistency_action_once.rb +6 -6
  72. data/lib/aspera/persistency_folder.rb +5 -9
  73. data/lib/aspera/preview/file_types.rb +6 -5
  74. data/lib/aspera/preview/generator.rb +25 -24
  75. data/lib/aspera/preview/options.rb +16 -14
  76. data/lib/aspera/preview/utils.rb +98 -98
  77. data/lib/aspera/{proxy_auto_config.erb.js → proxy_auto_config.js} +23 -31
  78. data/lib/aspera/proxy_auto_config.rb +111 -20
  79. data/lib/aspera/rest.rb +115 -113
  80. data/lib/aspera/rest_call_error.rb +2 -2
  81. data/lib/aspera/rest_error_analyzer.rb +23 -25
  82. data/lib/aspera/rest_errors_aspera.rb +15 -14
  83. data/lib/aspera/ssh.rb +12 -10
  84. data/lib/aspera/sync.rb +42 -41
  85. data/lib/aspera/temp_file_manager.rb +18 -14
  86. data/lib/aspera/timer_limiter.rb +2 -1
  87. data/lib/aspera/uri_reader.rb +7 -5
  88. data/lib/aspera/web_auth.rb +79 -76
  89. metadata +64 -21
  90. data/docs/Makefile +0 -65
  91. data/docs/README.erb.md +0 -4424
  92. data/docs/README.md +0 -13
  93. data/docs/diagrams.txt +0 -49
  94. data/docs/doc_tools.rb +0 -58
  95. data/lib/aspera/cli/plugins/shares2.rb +0 -114
  96. data/lib/aspera/fasp/default.rb +0 -17
@@ -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.to_s)
33
+ return @object.send(@attr_symb)
33
34
  end
34
35
 
35
36
  def value=(val)
36
- @object.send(@attr_symb.to_s+'=',val)
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.clone.push(:no,false)
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
- def enum_to_bool(enum);TRUE_VALUES.include?(enum);end
60
-
61
- # find shortened string value in allowed symbol list
62
- def self.get_from_list(shortval,descr,allowed_values)
63
- # we accept shortcuts
64
- matching_exact=allowed_values.select{|i| i.to_s.eql?(shortval)}
65
- return matching_exact.first if matching_exact.length == 1
66
- matching=allowed_values.select{|i| i.to_s.start_with?(shortval)}
67
- raise cli_bad_arg("unknown value for #{descr}: #{shortval}",allowed_values) if matching.empty?
68
- raise cli_bad_arg("ambigous shortcut for #{descr}: #{shortval}",matching) unless matching.length.eql?(1)
69
- return enum_to_bool(matching.first) if allowed_values.eql?(BOOLEAN_VALUES)
70
- return matching.first
71
- end
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
- def self.cli_bad_arg(error_msg,choices)
74
- return CliBadArgument.new(error_msg+"\nUse:\n"+choices.map{|c| "- #{c.to_s}\n"}.sort.join(''))
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
- self.set_obj_attr(:interactive,self,:ask_missing_mandatory)
118
- self.set_obj_attr(:ask_options,self,:ask_missing_optional)
119
- self.add_opt_boolean(:interactive,'use interactive input of missing params')
120
- self.add_opt_boolean(:ask_options,'ask even optional options')
121
- self.parse_options!
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 and value.start_with?('-')
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) and result.first.is_a?(Array)
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
- else
168
+ elsif is_type.eql?(:mandatory)
200
169
  # no value provided
201
- if is_type.eql?(:mandatory)
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=>type}
183
+ @declared_options[option_symbol]={type: type}
217
184
  # by default passwords and secrets are sensitive, else specify when declaring the option
218
- set_is_sensitive(option_symbol) if !%w{password secret key}.select{|i| option_symbol.to_s.end_with?(i)}.empty?
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,"default obj attr") if !default_value.nil?
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="default")
235
- if ! @declared_options.has_key?(option_symbol)
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 "ERROR: cannot set undeclared option"
200
+ raise 'ERROR: cannot set undeclared option'
238
201
  #declare_option(option_symbol)
239
202
  end
240
203
  value=ExtendedValue.instance.evaluate(value)
241
- Log.log.debug("set_option(#{where}) #{option_symbol}=#{value}")
242
- if @declared_options[option_symbol][:values].eql?(BOOLEAN_VALUES)
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 "error"
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 "unknown type"
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||='' unless @fail_on_missing_mandatory
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
- raise CliBadArgument,"Missing mandatory option: #{option_symbol}"
279
- end
280
- else # ask_missing_mandatory
281
- if @ask_missing_optional or is_type.eql?(:mandatory)
282
- expected=:single
283
- #print "please enter: #{option_symbol.to_s}"
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|((i.eql?(:yes) and value) or (i.eql?(:no) and not value))?highlight_current(i):i}.join(', ')
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),"cmdline")}
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,"VALUE"))
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,"cmdline") }
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,"DATE"))
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'; set_option(option_symbol,Manager.time_to_string(Time.now),"cmdline")
354
- when /^-([0-9]+)h/; set_option(option_symbol,Manager.time_to_string(Time.now-$1.to_i*3600),"cmdline")
355
- else set_option(option_symbol,v,"cmdline")
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=true)
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=$1
390
- value=$2
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(all=true)
405
- return @declared_options.keys.inject({}) do |h,option_symb|
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
- h[option_symb.to_s]=v if all or !v.nil?
408
- h
354
+ result[option_symb.to_s]=v unless only_defined && v.nil?
409
355
  end
410
- end
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("parse_options!".red)
361
+ Log.log.debug('parse_options!'.red)
434
362
  # first conf file, then env var
435
- apply_options_preset(@unprocessed_defaults,"file")
436
- apply_options_preset(@unprocessed_env,"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("before parse".red)
369
+ Log.log.debug('before parse'.red)
442
370
  @parser.parse!(@unprocessed_cmd_line_options)
443
- Log.log.debug("After parse".red)
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
@@ -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
- @@done=false
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,"ACTIONS shall be redefined by subclass" unless self.class.constants.include?(:ACTIONS)
22
+ raise StandardError,'ACTIONS shall be redefined by subclass' unless self.class.constants.include?(:ACTIONS)
21
23
  unless env[:skip_option_header]
22
- self.options.parser.separator ""
23
- self.options.parser.separator "COMMAND: #{self.class.name.split('::').last.downcase}"
24
- self.options.parser.separator "SUBCOMMANDS: #{self.class.const_get(:ACTIONS).map{ |p| p.to_s}.join(' ')}"
25
- self.options.parser.separator "OPTIONS:"
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=self.options.get_option(:id)
39
- res_id=self.options.get_next_argument('identifier') if res_id.nil?
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
- 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)
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=self.options.get_option(:value,:mandatory)
62
+ parameters=options.get_option(:value,:mandatory)
57
63
  end
58
64
  # parameters optional for list
59
65
  if [:list].include?(command)
60
- parameters=self.options.get_option(:value,:optional)
66
+ parameters=options.get_option(:value,:optional)
61
67
  end
62
68
  case command
63
69
  when :create
64
- return {:type => :single_object, :data=>rest_api.create(res_class_path,parameters)[:data], :fields=>display_fields}
70
+ return {type: :single_object, data: rest_api.create(res_class_path,parameters)[:data], fields: display_fields}
65
71
  when :show
66
- return {:type => :single_object, :data=>rest_api.read(one_res_path)[:data], :fields=>display_fields}
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 {:type => :object_list, :data=>data, :fields=>display_fields}
81
+ return {type: :object_list, data: data, fields: display_fields}
76
82
  when :modify
77
- property=self.options.get_option(:property,:optional)
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("deleted")
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,display_fields,id_symb,id_default=nil,use_subkey=false)
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=self.options.get_next_command(ALL_OPS)
94
- return entity_command(command,rest_api,res_class_path,display_fields,id_symb,id_default,use_subkey)
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=self.options.get_next_command(ACTIONS)
12
+ command=options.get_next_command(ACTIONS)
13
13
  case command
14
14
  when :entitlement
15
- entitlement_id = self.options.get_option(:username,:mandatory)
16
- customer_id = self.options.get_option(:password,:mandatory)
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 {:type=>:single_object, :data=>api_metering.read('entitlement')[:data]}
18
+ return {type: :single_object, data: api_metering.read('entitlement')[:data]}
19
19
  end
20
20
  end
21
21
  end # Aspera