aspera-cli 4.0.0.pre1

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.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +3592 -0
  3. data/bin/ascli +7 -0
  4. data/bin/asession +89 -0
  5. data/docs/Makefile +59 -0
  6. data/docs/README.erb.md +3012 -0
  7. data/docs/README.md +13 -0
  8. data/docs/diagrams.txt +49 -0
  9. data/docs/secrets.make +38 -0
  10. data/docs/test_env.conf +117 -0
  11. data/docs/transfer_spec.html +99 -0
  12. data/examples/aoc.rb +17 -0
  13. data/examples/proxy.pac +60 -0
  14. data/examples/transfer.rb +115 -0
  15. data/lib/aspera/api_detector.rb +60 -0
  16. data/lib/aspera/ascmd.rb +151 -0
  17. data/lib/aspera/ats_api.rb +43 -0
  18. data/lib/aspera/cli/basic_auth_plugin.rb +38 -0
  19. data/lib/aspera/cli/extended_value.rb +88 -0
  20. data/lib/aspera/cli/formater.rb +238 -0
  21. data/lib/aspera/cli/listener/line_dump.rb +17 -0
  22. data/lib/aspera/cli/listener/logger.rb +20 -0
  23. data/lib/aspera/cli/listener/progress.rb +52 -0
  24. data/lib/aspera/cli/listener/progress_multi.rb +91 -0
  25. data/lib/aspera/cli/main.rb +304 -0
  26. data/lib/aspera/cli/manager.rb +440 -0
  27. data/lib/aspera/cli/plugin.rb +90 -0
  28. data/lib/aspera/cli/plugins/alee.rb +24 -0
  29. data/lib/aspera/cli/plugins/ats.rb +231 -0
  30. data/lib/aspera/cli/plugins/bss.rb +71 -0
  31. data/lib/aspera/cli/plugins/config.rb +806 -0
  32. data/lib/aspera/cli/plugins/console.rb +62 -0
  33. data/lib/aspera/cli/plugins/cos.rb +106 -0
  34. data/lib/aspera/cli/plugins/faspex.rb +377 -0
  35. data/lib/aspera/cli/plugins/faspex5.rb +93 -0
  36. data/lib/aspera/cli/plugins/node.rb +438 -0
  37. data/lib/aspera/cli/plugins/oncloud.rb +937 -0
  38. data/lib/aspera/cli/plugins/orchestrator.rb +169 -0
  39. data/lib/aspera/cli/plugins/preview.rb +464 -0
  40. data/lib/aspera/cli/plugins/server.rb +216 -0
  41. data/lib/aspera/cli/plugins/shares.rb +63 -0
  42. data/lib/aspera/cli/plugins/shares2.rb +114 -0
  43. data/lib/aspera/cli/plugins/sync.rb +65 -0
  44. data/lib/aspera/cli/plugins/xnode.rb +115 -0
  45. data/lib/aspera/cli/transfer_agent.rb +251 -0
  46. data/lib/aspera/cli/version.rb +5 -0
  47. data/lib/aspera/colors.rb +39 -0
  48. data/lib/aspera/command_line_builder.rb +137 -0
  49. data/lib/aspera/fasp/aoc.rb +24 -0
  50. data/lib/aspera/fasp/connect.rb +99 -0
  51. data/lib/aspera/fasp/error.rb +21 -0
  52. data/lib/aspera/fasp/error_info.rb +60 -0
  53. data/lib/aspera/fasp/http_gw.rb +81 -0
  54. data/lib/aspera/fasp/installation.rb +240 -0
  55. data/lib/aspera/fasp/listener.rb +11 -0
  56. data/lib/aspera/fasp/local.rb +377 -0
  57. data/lib/aspera/fasp/manager.rb +69 -0
  58. data/lib/aspera/fasp/node.rb +88 -0
  59. data/lib/aspera/fasp/parameters.rb +235 -0
  60. data/lib/aspera/fasp/resume_policy.rb +76 -0
  61. data/lib/aspera/fasp/uri.rb +51 -0
  62. data/lib/aspera/faspex_gw.rb +196 -0
  63. data/lib/aspera/hash_ext.rb +28 -0
  64. data/lib/aspera/log.rb +80 -0
  65. data/lib/aspera/nagios.rb +71 -0
  66. data/lib/aspera/node.rb +14 -0
  67. data/lib/aspera/oauth.rb +319 -0
  68. data/lib/aspera/on_cloud.rb +421 -0
  69. data/lib/aspera/open_application.rb +72 -0
  70. data/lib/aspera/persistency_action_once.rb +42 -0
  71. data/lib/aspera/persistency_folder.rb +91 -0
  72. data/lib/aspera/preview/file_types.rb +300 -0
  73. data/lib/aspera/preview/generator.rb +258 -0
  74. data/lib/aspera/preview/image_error.png +0 -0
  75. data/lib/aspera/preview/options.rb +35 -0
  76. data/lib/aspera/preview/utils.rb +131 -0
  77. data/lib/aspera/preview/video_error.png +0 -0
  78. data/lib/aspera/proxy_auto_config.erb.js +287 -0
  79. data/lib/aspera/proxy_auto_config.rb +34 -0
  80. data/lib/aspera/rest.rb +296 -0
  81. data/lib/aspera/rest_call_error.rb +13 -0
  82. data/lib/aspera/rest_error_analyzer.rb +98 -0
  83. data/lib/aspera/rest_errors_aspera.rb +58 -0
  84. data/lib/aspera/ssh.rb +53 -0
  85. data/lib/aspera/sync.rb +82 -0
  86. data/lib/aspera/temp_file_manager.rb +37 -0
  87. data/lib/aspera/uri_reader.rb +25 -0
  88. metadata +288 -0
@@ -0,0 +1,440 @@
1
+ require 'aspera/colors'
2
+ require 'aspera/log'
3
+ require 'aspera/cli/extended_value'
4
+ require 'optparse'
5
+
6
+ module Aspera
7
+ module Cli
8
+ # raised by cli on error conditions
9
+ class CliError < StandardError; end
10
+
11
+ # raised when an unexpected argument is provided
12
+ class CliBadArgument < CliError; end
13
+
14
+ class CliNoSuchId < CliError
15
+ def initialize(res_type,res_id)
16
+ msg="No such #{res_type} identifier: #{res_id}"
17
+ super(msg)
18
+ end
19
+ end
20
+
21
+ # option is retrieved from another object using accessor
22
+ class AttrAccessor
23
+ #attr_accessor :object
24
+ #attr_accessor :attr_symb
25
+ def initialize(object,attr_symb)
26
+ @object=object
27
+ @attr_symb=attr_symb
28
+ end
29
+
30
+ def value
31
+ @object.send(@attr_symb.to_s)
32
+ end
33
+
34
+ def value=(val)
35
+ @object.send(@attr_symb.to_s+'=',val)
36
+ end
37
+ end
38
+
39
+ # parse command line options
40
+ # arguments options start with '-', others are commands
41
+ # resolves on extended value syntax
42
+ class Manager
43
+ def self.time_to_string(time)
44
+ time.strftime("%Y-%m-%d %H:%M:%S")
45
+ end
46
+
47
+ # boolean options are set to true/false from the following values
48
+ TRUE_VALUES=[:yes,true]
49
+ BOOLEAN_VALUES=TRUE_VALUES.clone.push(:no,false)
50
+ BOOLEAN_SIMPLE=[:yes,:no]
51
+ # option name separator on command line
52
+ OPTION_SEP_LINE='-'
53
+ # option name separator in code (symbol)
54
+ OPTION_SEP_NAME='_'
55
+
56
+ private_constant :TRUE_VALUES,:BOOLEAN_VALUES,:BOOLEAN_SIMPLE,:OPTION_SEP_LINE,:OPTION_SEP_NAME
57
+
58
+ def enum_to_bool(enum);TRUE_VALUES.include?(enum);end
59
+
60
+ # find shortened string value in allowed symbol list
61
+ def self.get_from_list(shortval,descr,allowed_values)
62
+ # we accept shortcuts
63
+ matching_exact=allowed_values.select{|i| i.to_s.eql?(shortval)}
64
+ return matching_exact.first if matching_exact.length == 1
65
+ matching=allowed_values.select{|i| i.to_s.start_with?(shortval)}
66
+ raise cli_bad_arg("unknown value for #{descr}: #{shortval}",allowed_values) if matching.empty?
67
+ raise cli_bad_arg("ambigous shortcut for #{descr}: #{shortval}",matching) unless matching.length.eql?(1)
68
+ return enum_to_bool(matching.first) if allowed_values.eql?(BOOLEAN_VALUES)
69
+ return matching.first
70
+ end
71
+
72
+ def self.cli_bad_arg(error_msg,choices)
73
+ return CliBadArgument.new(error_msg+"\nUse:\n"+choices.map{|c| "- #{c.to_s}\n"}.sort.join(''))
74
+ end
75
+
76
+ attr_reader :parser
77
+ attr_accessor :ask_missing_mandatory
78
+ attr_accessor :ask_missing_optional
79
+
80
+ #
81
+ def initialize(program_name,argv,app_banner)
82
+ # command line values not starting with '-'
83
+ @unprocessed_cmd_line_arguments=[]
84
+ # command line values starting with '-'
85
+ @unprocessed_cmd_line_options=[]
86
+ # a copy of all initial options
87
+ @initial_cli_options=[]
88
+ # option description: key = option symbol, value=hash, :type, :accessor, :value, :accepted
89
+ @declared_options={}
90
+ # do we ask missing options and arguments to user ?
91
+ @ask_missing_mandatory=false # STDIN.isatty
92
+ # ask optional options if not provided and in interactive
93
+ @ask_missing_optional=false
94
+ # those must be set before parse, parse consumes those defined only
95
+ @unprocessed_defaults=[]
96
+ @unprocessed_env=[]
97
+ # Note: was initially inherited but it is prefered to have specific methods
98
+ @parser=OptionParser.new
99
+ @parser.program_name=program_name
100
+ @parser.banner=app_banner
101
+ # options can also be provided by env vars : --param-name -> ASLMCLI_PARAM_NAME
102
+ env_prefix=program_name.upcase+OPTION_SEP_NAME
103
+ ENV.each do |k,v|
104
+ if k.start_with?(env_prefix)
105
+ @unprocessed_env.push([k[env_prefix.length..-1].downcase.to_sym,v])
106
+ end
107
+ end
108
+ Log.log.debug("env=#{@unprocessed_env}".red)
109
+ # banner is empty when help is generated for every plugin
110
+ unless app_banner.empty?
111
+ @parser.separator("")
112
+ @parser.separator("OPTIONS: global")
113
+ self.set_obj_attr(:interactive,self,:ask_missing_mandatory)
114
+ self.set_obj_attr(:ask_options,self,:ask_missing_optional)
115
+ self.add_opt_boolean(:interactive,"use interactive input of missing params")
116
+ self.add_opt_boolean(:ask_options,"ask even optional options")
117
+ self.parse_options!
118
+ end
119
+ @unprocessed_cmd_line_options=[]
120
+ @unprocessed_cmd_line_arguments=[]
121
+ process_options=true
122
+ while !argv.empty?
123
+ value=argv.shift
124
+ if process_options and value.start_with?('-')
125
+ if value.eql?('--')
126
+ process_options=false
127
+ else
128
+ @unprocessed_cmd_line_options.push(value)
129
+ end
130
+ else
131
+ @unprocessed_cmd_line_arguments.push(value)
132
+ end
133
+ end
134
+ @initial_cli_options=@unprocessed_cmd_line_options.dup
135
+ Log.log.debug("add_cmd_line_options:commands/args=#{@unprocessed_cmd_line_arguments},options=#{@unprocessed_cmd_line_options}".red)
136
+ end
137
+
138
+ def get_interactive(type,descr,expected=:single)
139
+ if !@ask_missing_mandatory
140
+ if expected.is_a?(Array)
141
+ raise self.class.cli_bad_arg("missing: #{descr}",expected)
142
+ end
143
+ raise CliBadArgument,"missing argument (#{expected}): #{descr}"
144
+ end
145
+ result=nil
146
+ # ask interactively
147
+ case expected
148
+ when :multiple
149
+ result=[]
150
+ puts " (one per line, end with empty line)"
151
+ loop do
152
+ print "#{type}: #{descr}> "
153
+ entry=STDIN.gets.chomp
154
+ break if entry.empty?
155
+ result.push(ExtendedValue.instance.evaluate(entry))
156
+ end
157
+ when :single
158
+ print "#{type}: #{descr}> "
159
+ result=ExtendedValue.instance.evaluate(STDIN.gets.chomp)
160
+ else # one fixed
161
+ print "#{expected.join(' ')}\n#{type}: #{descr}> "
162
+ result=self.class.get_from_list(STDIN.gets.chomp,descr,expected)
163
+ end
164
+ return result
165
+ end
166
+
167
+ def get_next_command(command_list); return get_next_argument('command',command_list); end
168
+
169
+ # @param expected is
170
+ # - Array of allowed value (single value)
171
+ # - :multiple for remaining values
172
+ # - :single for a single unconstrained value
173
+ # @param is_type : :mandatory or :optional
174
+ # @return value, list or nil
175
+ def get_next_argument(descr,expected=:single,is_type=:mandatory)
176
+ result=nil
177
+ if !@unprocessed_cmd_line_arguments.empty?
178
+ # there are values
179
+ case expected
180
+ when :single
181
+ result=ExtendedValue.instance.evaluate(@unprocessed_cmd_line_arguments.shift)
182
+ when :multiple
183
+ result = @unprocessed_cmd_line_arguments.shift(@unprocessed_cmd_line_arguments.length).map{|v|ExtendedValue.instance.evaluate(v)}
184
+ # if expecting list and only one arg of type array : it is the list
185
+ if result.length.eql?(1) and result.first.is_a?(Array)
186
+ result=result.first
187
+ end
188
+ else
189
+ result=self.class.get_from_list(@unprocessed_cmd_line_arguments.shift,descr,expected)
190
+ end
191
+ else
192
+ # no value provided
193
+ if is_type.eql?(:mandatory)
194
+ result=get_interactive(:argument,descr,expected)
195
+ end
196
+ end
197
+ Log.log.debug("#{descr}=#{result}")
198
+ return result
199
+ end
200
+
201
+ # declare option of type :accessor, or :value
202
+ def declare_option(option_symbol,type)
203
+ Log.log.debug("declare_option: #{option_symbol}: #{type}: skip=#{@declared_options.has_key?(option_symbol)}".green)
204
+ if @declared_options.has_key?(option_symbol)
205
+ raise "INTERNAL ERROR: option #{option_symbol} already declared. only accessor can be redeclared and ignored" unless @declared_options[option_symbol][:type].eql?(:accessor)
206
+ return
207
+ end
208
+ @declared_options[option_symbol]={:type=>type}
209
+ end
210
+
211
+ # define option with handler
212
+ def set_obj_attr(option_symbol,object,attr_symb,default_value=nil)
213
+ Log.log.debug("set attr obj #{option_symbol} (#{object},#{attr_symb})")
214
+ declare_option(option_symbol,:accessor)
215
+ @declared_options[option_symbol][:accessor]=AttrAccessor.new(object,attr_symb)
216
+ set_option(option_symbol,default_value,"default obj attr") if !default_value.nil?
217
+ end
218
+
219
+ # set an option value by name, either store value or call handler
220
+ def set_option(option_symbol,value,where="default")
221
+ if ! @declared_options.has_key?(option_symbol)
222
+ Log.log.debug("set unknown option: #{option_symbol}")
223
+ raise "ERROR"
224
+ #declare_option(option_symbol)
225
+ end
226
+ value=ExtendedValue.instance.evaluate(value)
227
+ Log.log.debug("set_option(#{where}) #{option_symbol}=#{value}")
228
+ if @declared_options[option_symbol][:values].eql?(BOOLEAN_VALUES)
229
+ value=enum_to_bool(value)
230
+ end
231
+ Log.log.debug("set #{option_symbol}=#{value} (#{@declared_options[option_symbol][:type]}) : #{where}".blue)
232
+ case @declared_options[option_symbol][:type]
233
+ when :accessor
234
+ @declared_options[option_symbol][:accessor].value=value
235
+ when :value
236
+ @declared_options[option_symbol][:value]=value
237
+ else # nil or other
238
+ raise "error"
239
+ end
240
+ end
241
+
242
+ # get an option value by name
243
+ # either return value or call handler, can return nil
244
+ # ask interactively if requested/required
245
+ def get_option(option_symbol,is_type=:optional)
246
+ result=nil
247
+ if @declared_options.has_key?(option_symbol)
248
+ case @declared_options[option_symbol][:type]
249
+ when :accessor
250
+ result=@declared_options[option_symbol][:accessor].value
251
+ when :value
252
+ result=@declared_options[option_symbol][:value]
253
+ else
254
+ raise "unknown type"
255
+ end
256
+ Log.log.debug("get #{option_symbol} (#{@declared_options[option_symbol][:type]}) : #{result}")
257
+ end
258
+ Log.log.debug("interactive=#{@ask_missing_mandatory}")
259
+ if result.nil?
260
+ if !@ask_missing_mandatory
261
+ if is_type.eql?(:mandatory)
262
+ raise CliBadArgument,"Missing mandatory option: #{option_symbol}"
263
+ end
264
+ else # ask_missing_mandatory
265
+ if @ask_missing_optional or is_type.eql?(:mandatory)
266
+ expected=:single
267
+ #print "please enter: #{option_symbol.to_s}"
268
+ if @declared_options.has_key?(option_symbol) and @declared_options[option_symbol].has_key?(:values)
269
+ expected=@declared_options[option_symbol][:values]
270
+ end
271
+ result=get_interactive(:option,option_symbol.to_s,expected)
272
+ set_option(option_symbol,result,"interactive")
273
+ end
274
+ end
275
+ end
276
+ return result
277
+ end
278
+
279
+ # param must be hash
280
+ def add_option_preset(preset_hash,op=:push)
281
+ Log.log.debug("add_option_preset=#{preset_hash}")
282
+ raise "internal error: setting default with no hash: #{preset_hash.class}" if !preset_hash.is_a?(Hash)
283
+ # incremental override
284
+ preset_hash.each{|k,v|@unprocessed_defaults.send(op,[k.to_sym,v])}
285
+ end
286
+
287
+ # generate command line option from option symbol
288
+ def symbol_to_option(symbol,opt_val)
289
+ result='--'+symbol.to_s.gsub(OPTION_SEP_NAME,OPTION_SEP_LINE)
290
+ result=result+'='+opt_val unless opt_val.nil?
291
+ return result
292
+ end
293
+
294
+ def highlight_current(value)
295
+ STDOUT.isatty ? value.to_s.red.bold : "[#{value}]"
296
+ end
297
+
298
+ # define an option with restricted values
299
+ def add_opt_list(option_symbol,values,help,*on_args)
300
+ declare_option(option_symbol,:value)
301
+ Log.log.debug("add_opt_list #{option_symbol}")
302
+ on_args.unshift(symbol_to_option(option_symbol,'ENUM'))
303
+ # this option value must be a symbol
304
+ @declared_options[option_symbol][:values]=values
305
+ value=get_option(option_symbol)
306
+ help_values=values.map{|i|i.eql?(value)?highlight_current(i):i}.join(', ')
307
+ if values.eql?(BOOLEAN_VALUES)
308
+ help_values=BOOLEAN_SIMPLE.map{|i|((i.eql?(:yes) and value) or (i.eql?(:no) and not value))?highlight_current(i):i}.join(', ')
309
+ end
310
+ on_args.push(values)
311
+ on_args.push("#{help}: #{help_values}")
312
+ Log.log.debug("on_args=#{on_args}")
313
+ @parser.on(*on_args){|v|set_option(option_symbol,self.class.get_from_list(v.to_s,help,values),"cmdline")}
314
+ end
315
+
316
+ def add_opt_boolean(option_symbol,help,*on_args)
317
+ add_opt_list(option_symbol,BOOLEAN_VALUES,help,*on_args)
318
+ end
319
+
320
+ # define an option with open values
321
+ def add_opt_simple(option_symbol,*on_args)
322
+ declare_option(option_symbol,:value)
323
+ Log.log.debug("add_opt_simple #{option_symbol}")
324
+ on_args.unshift(symbol_to_option(option_symbol,"VALUE"))
325
+ Log.log.debug("on_args=#{on_args}")
326
+ @parser.on(*on_args) { |v| set_option(option_symbol,v,"cmdline") }
327
+ end
328
+
329
+ # define an option with date format
330
+ def add_opt_date(option_symbol,*on_args)
331
+ declare_option(option_symbol,:value)
332
+ Log.log.debug("add_opt_date #{option_symbol}")
333
+ on_args.unshift(symbol_to_option(option_symbol,"DATE"))
334
+ Log.log.debug("on_args=#{on_args}")
335
+ @parser.on(*on_args) do |v|
336
+ case v
337
+ when 'now'; set_option(option_symbol,Manager.time_to_string(Time.now),"cmdline")
338
+ when /^-([0-9]+)h/; set_option(option_symbol,Manager.time_to_string(Time.now-$1.to_i*3600),"cmdline")
339
+ else set_option(option_symbol,v,"cmdline")
340
+ end
341
+ end
342
+ end
343
+
344
+ # define an option without value
345
+ def add_opt_switch(option_symbol,*on_args,&block)
346
+ Log.log.debug("add_opt_on #{option_symbol}")
347
+ on_args.unshift(symbol_to_option(option_symbol,nil))
348
+ Log.log.debug("on_args=#{on_args}")
349
+ @parser.on(*on_args,&block)
350
+ end
351
+
352
+ # check if there were unprocessed values to generate error
353
+ def command_or_arg_empty?
354
+ return @unprocessed_cmd_line_arguments.empty?
355
+ end
356
+
357
+ # unprocessed options or arguments ?
358
+ def final_errors
359
+ result=[]
360
+ result.push("unprocessed options: #{@unprocessed_cmd_line_options}") unless @unprocessed_cmd_line_options.empty?
361
+ result.push("unprocessed values: #{@unprocessed_cmd_line_arguments}") unless @unprocessed_cmd_line_arguments.empty?
362
+ return result
363
+ end
364
+
365
+ # get all original options on command line used to generate a config in config file
366
+ def get_options_table(remove_from_remaining=true)
367
+ result={}
368
+ @initial_cli_options.each do |optionval|
369
+ case optionval
370
+ when /^--([^=]+)$/
371
+ # ignore
372
+ when /^--([^=]+)=(.*)$/
373
+ name=$1
374
+ value=$2
375
+ name.gsub!(OPTION_SEP_LINE,OPTION_SEP_NAME)
376
+ value=ExtendedValue.instance.evaluate(value)
377
+ Log.log.debug("option #{name}=#{value}")
378
+ result[name]=value
379
+ @unprocessed_cmd_line_options.delete(optionval) if remove_from_remaining
380
+ else
381
+ raise CliBadArgument,"wrong option format: #{optionval}"
382
+ end
383
+ end
384
+ return result
385
+ end
386
+
387
+ # return options as taken from config file and command line just before command execution
388
+ def declared_options(all=true)
389
+ return @declared_options.keys.inject({}) do |h,option_symb|
390
+ v=get_option(option_symb)
391
+ h[option_symb.to_s]=v if all or !v.nil?
392
+ h
393
+ end
394
+ end
395
+
396
+ def apply_options_preset(preset,where,force=false)
397
+ unprocessed=[]
398
+ preset.each do |pair|
399
+ k,v=*pair
400
+ if @declared_options.has_key?(k)
401
+ # constrained parameters as string are revert to symbol
402
+ if @declared_options[k].has_key?(:values) and v.is_a?(String)
403
+ v=self.class.get_from_list(v,k.to_s+" in #{where}",@declared_options[k][:values])
404
+ end
405
+ set_option(k,v,where)
406
+ else
407
+ unprocessed.push(pair)
408
+ end
409
+ end
410
+ # keep only unprocessed values for next parse
411
+ preset.clear
412
+ preset.push(*unprocessed)
413
+ end
414
+
415
+ # removes already known options from the list
416
+ def parse_options!
417
+ Log.log.debug("parse_options!".red)
418
+ # first conf file, then env var
419
+ apply_options_preset(@unprocessed_defaults,"file")
420
+ apply_options_preset(@unprocessed_env,"env")
421
+ # command line override
422
+ unknown_options=[]
423
+ begin
424
+ # remove known options one by one, exception if unknown
425
+ Log.log.debug("before parse".red)
426
+ @parser.parse!(@unprocessed_cmd_line_options)
427
+ Log.log.debug("After parse".red)
428
+ rescue OptionParser::InvalidOption => e
429
+ Log.log.debug("InvalidOption #{e}".red)
430
+ # save for later processing
431
+ unknown_options.push(e.args.first)
432
+ retry
433
+ end
434
+ Log.log.debug("remains: #{unknown_options}")
435
+ # set unprocessed options for next time
436
+ @unprocessed_cmd_line_options=unknown_options
437
+ end
438
+ end
439
+ end
440
+ end
@@ -0,0 +1,90 @@
1
+ module Aspera
2
+ module Cli
3
+ # base class for plugins modules
4
+ class Plugin
5
+ GLOBAL_OPS=[:create,:list]
6
+ INSTANCE_OPS=[:modify,:delete,:show]
7
+ ALL_OPS=[GLOBAL_OPS,INSTANCE_OPS].flatten
8
+ #private_constant :GLOBAL_OPS,:INSTANCE_OPS,:ALL_OPS
9
+
10
+ @@done=false
11
+
12
+ def initialize(env)
13
+ @agents=env
14
+ raise StandardError,"execute_action shall be redefined by subclass #{self.class}" unless respond_to?(:execute_action)
15
+ raise StandardError,"ACTIONS shall be redefined by subclass" unless self.class.constants.include?(:ACTIONS)
16
+ unless env[:skip_option_header]
17
+ self.options.parser.separator ""
18
+ self.options.parser.separator "COMMAND: #{self.class.name.split('::').last.downcase}"
19
+ self.options.parser.separator "SUBCOMMANDS: #{self.class.const_get(:ACTIONS).map{ |p| p.to_s}.join(' ')}"
20
+ self.options.parser.separator "OPTIONS:"
21
+ end
22
+ unless @@done
23
+ self.options.add_opt_simple(:value,"extended value for create, update, list filter")
24
+ self.options.add_opt_simple(:property,"name of property to set")
25
+ self.options.add_opt_simple(:id,"resource identifier (#{INSTANCE_OPS.join(",")})")
26
+ self.options.parse_options!
27
+ @@done=true
28
+ end
29
+ end
30
+
31
+ def entity_command(command,rest_api,res_class_path,display_fields,id_symb,id_default=nil,subkey=false)
32
+ if INSTANCE_OPS.include?(command)
33
+ begin
34
+ one_res_id=self.options.get_option(id_symb,:mandatory)
35
+ rescue => e
36
+ raise e if id_default.nil?
37
+ one_res_id=id_default
38
+ end
39
+ one_res_path="#{res_class_path}/#{one_res_id}"
40
+ end
41
+ # parameters mandatory for create/modify
42
+ if [:create,:modify].include?(command)
43
+ parameters=self.options.get_option(:value,:mandatory)
44
+ end
45
+ # parameters optional for list
46
+ if [:list].include?(command)
47
+ parameters=self.options.get_option(:value,:optional)
48
+ end
49
+ case command
50
+ when :create
51
+ return {:type => :single_object, :data=>rest_api.create(res_class_path,parameters)[:data], :fields=>display_fields}
52
+ when :show
53
+ return {:type => :single_object, :data=>rest_api.read(one_res_path)[:data], :fields=>display_fields}
54
+ when :list
55
+ resp=rest_api.read(res_class_path,parameters)
56
+ data=resp[:data]
57
+ if resp[:http]['Content-Type'].start_with?('application/vnd.api+json')
58
+ data=resp[:data][res_class_path]
59
+ end
60
+ data=data[res_class_path] if subkey
61
+ return {:type => :object_list, :data=>data, :fields=>display_fields}
62
+ when :modify
63
+ property=self.options.get_option(:property,:optional)
64
+ parameters={property => parameters} unless property.nil?
65
+ rest_api.update(one_res_path,parameters)
66
+ return Main.result_status('modified')
67
+ when :delete
68
+ rest_api.delete(one_res_path)
69
+ return Main.result_status("deleted")
70
+ end
71
+ end
72
+
73
+ # implement generic rest operations on given resource path
74
+ def entity_action(rest_api,res_class_path,display_fields,id_symb,id_default=nil,subkey=false)
75
+ #res_name=res_class_path.gsub(%r{^.*/},'').gsub(%r{s$},'').gsub('_',' ')
76
+ command=self.options.get_next_command(ALL_OPS)
77
+ return entity_command(command,rest_api,res_class_path,display_fields,id_symb,id_default,subkey)
78
+ end
79
+
80
+ def options;@agents[:options];end
81
+
82
+ def transfer;@agents[:transfer];end
83
+
84
+ def config;return @agents[:config];end
85
+
86
+ def format;return @agents[:formater];end
87
+
88
+ end # Plugin
89
+ end # Cli
90
+ end # Aspera