aspera-cli 4.0.0.pre1

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