aspera-cli 4.17.0 → 4.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -4
  3. data/CHANGELOG.md +23 -0
  4. data/CONTRIBUTING.md +15 -1
  5. data/README.md +620 -378
  6. data/bin/ascli +5 -0
  7. data/bin/asession +2 -2
  8. data/lib/aspera/agent/alpha.rb +6 -4
  9. data/lib/aspera/agent/base.rb +9 -6
  10. data/lib/aspera/agent/connect.rb +4 -4
  11. data/lib/aspera/agent/direct.rb +56 -37
  12. data/lib/aspera/agent/httpgw.rb +23 -324
  13. data/lib/aspera/agent/node.rb +19 -20
  14. data/lib/aspera/agent/trsdk.rb +19 -20
  15. data/lib/aspera/api/aoc.rb +17 -14
  16. data/lib/aspera/api/cos_node.rb +4 -4
  17. data/lib/aspera/api/httpgw.rb +339 -0
  18. data/lib/aspera/api/node.rb +34 -21
  19. data/lib/aspera/ascmd.rb +4 -3
  20. data/lib/aspera/ascp/installation.rb +15 -7
  21. data/lib/aspera/ascp/management.rb +2 -2
  22. data/lib/aspera/cli/basic_auth_plugin.rb +5 -9
  23. data/lib/aspera/cli/extended_value.rb +12 -6
  24. data/lib/aspera/cli/formatter.rb +155 -65
  25. data/lib/aspera/cli/hints.rb +18 -0
  26. data/lib/aspera/cli/main.rb +22 -29
  27. data/lib/aspera/cli/manager.rb +53 -36
  28. data/lib/aspera/cli/plugin.rb +26 -17
  29. data/lib/aspera/cli/plugin_factory.rb +31 -20
  30. data/lib/aspera/cli/plugins/alee.rb +14 -2
  31. data/lib/aspera/cli/plugins/aoc.rb +141 -131
  32. data/lib/aspera/cli/plugins/ats.rb +1 -1
  33. data/lib/aspera/cli/plugins/config.rb +52 -46
  34. data/lib/aspera/cli/plugins/console.rb +8 -5
  35. data/lib/aspera/cli/plugins/faspex.rb +27 -19
  36. data/lib/aspera/cli/plugins/faspex5.rb +222 -149
  37. data/lib/aspera/cli/plugins/faspio.rb +85 -0
  38. data/lib/aspera/cli/plugins/httpgw.rb +55 -0
  39. data/lib/aspera/cli/plugins/node.rb +86 -29
  40. data/lib/aspera/cli/plugins/orchestrator.rb +31 -29
  41. data/lib/aspera/cli/plugins/preview.rb +6 -2
  42. data/lib/aspera/cli/plugins/server.rb +5 -5
  43. data/lib/aspera/cli/plugins/shares.rb +16 -14
  44. data/lib/aspera/cli/sync_actions.rb +6 -6
  45. data/lib/aspera/cli/transfer_agent.rb +5 -4
  46. data/lib/aspera/cli/version.rb +1 -1
  47. data/lib/aspera/environment.rb +7 -6
  48. data/lib/aspera/faspex_gw.rb +5 -4
  49. data/lib/aspera/faspex_postproc.rb +2 -2
  50. data/lib/aspera/log.rb +6 -3
  51. data/lib/aspera/node_simulator.rb +2 -2
  52. data/lib/aspera/oauth/base.rb +31 -19
  53. data/lib/aspera/oauth/factory.rb +12 -13
  54. data/lib/aspera/oauth/generic.rb +1 -0
  55. data/lib/aspera/oauth/jwt.rb +18 -15
  56. data/lib/aspera/oauth/url_json.rb +8 -6
  57. data/lib/aspera/open_application.rb +5 -7
  58. data/lib/aspera/persistency_folder.rb +2 -2
  59. data/lib/aspera/preview/generator.rb +3 -3
  60. data/lib/aspera/preview/options.rb +3 -3
  61. data/lib/aspera/preview/terminal.rb +4 -4
  62. data/lib/aspera/preview/utils.rb +3 -3
  63. data/lib/aspera/proxy_auto_config.rb +5 -1
  64. data/lib/aspera/rest.rb +60 -74
  65. data/lib/aspera/rest_call_error.rb +1 -1
  66. data/lib/aspera/rest_error_analyzer.rb +2 -2
  67. data/lib/aspera/rest_errors_aspera.rb +1 -1
  68. data/lib/aspera/resumer.rb +1 -1
  69. data/lib/aspera/secret_hider.rb +2 -4
  70. data/lib/aspera/ssh.rb +1 -1
  71. data/lib/aspera/transfer/parameters.rb +39 -36
  72. data/lib/aspera/transfer/spec.rb +2 -0
  73. data/lib/aspera/transfer/sync.rb +2 -1
  74. data/lib/aspera/transfer/uri.rb +1 -1
  75. data/lib/aspera/uri_reader.rb +5 -4
  76. data/lib/aspera/web_auth.rb +1 -1
  77. data/lib/aspera/web_server_simple.rb +4 -3
  78. data.tar.gz.sig +0 -0
  79. metadata +5 -3
  80. metadata.gz.sig +0 -0
  81. data/lib/aspera/cli/plugins/bss.rb +0 -71
@@ -56,6 +56,9 @@ module Aspera
56
56
  OPTION_SEP_SYMBOL = '_'
57
57
  SOURCE_USER = 'cmdline' # cspell:disable-line
58
58
  TYPE_INTEGER = [Integer].freeze
59
+ OPTION_VALUE_SEPARATOR = '='
60
+ OPTION_PREFIX = '--'
61
+ OPTIONS_STOP = '--'
59
62
 
60
63
  private_constant :FALSE_VALUES, :TRUE_VALUES, :BOOLEAN_VALUES, :OPTION_SEP_LINE, :OPTION_SEP_SYMBOL, :SOURCE_USER, :TYPE_INTEGER
61
64
 
@@ -94,7 +97,7 @@ module Aspera
94
97
  end
95
98
 
96
99
  def option_name_to_line(name)
97
- return "--#{name.to_s.gsub(OPTION_SEP_SYMBOL, OPTION_SEP_LINE)}"
100
+ return "#{OPTION_PREFIX}#{name.to_s.gsub(OPTION_SEP_SYMBOL, OPTION_SEP_LINE)}"
98
101
  end
99
102
 
100
103
  # @param what [Symbol] :option or :argument
@@ -115,22 +118,24 @@ module Aspera
115
118
  attr_writer :fail_on_missing_mandatory
116
119
 
117
120
  def initialize(program_name)
118
- # command line values not starting with '-'
121
+ # command line values *not* starting with '-'
119
122
  @unprocessed_cmd_line_arguments = []
120
123
  # command line values starting with '-'
121
124
  @unprocessed_cmd_line_options = []
122
125
  # a copy of all initial options
123
126
  @initial_cli_options = []
124
- # option description: key = option symbol, value=hash, :read_write, :accessor, :value, :accepted
127
+ # option description: key = option symbol, value=Hash, :read_write, :accessor, :value, :accepted
125
128
  @declared_options = {}
126
129
  # do we ask missing options and arguments to user ?
127
130
  @ask_missing_mandatory = false # STDIN.isatty
128
131
  # ask optional options if not provided and in interactive
129
132
  @ask_missing_optional = false
130
133
  @fail_on_missing_mandatory = true
131
- # those must be set before parse, parse consumes those defined only
132
- @unprocessed_defaults = []
133
- @unprocessed_env = []
134
+ # Array of [key(sym), value]
135
+ # those must be set before parse
136
+ # parse consumes those defined only
137
+ @option_pairs_batch = {}
138
+ @option_pairs_env = {}
134
139
  # NOTE: was initially inherited but it is preferred to have specific methods
135
140
  @parser = OptionParser.new
136
141
  @parser.program_name = program_name
@@ -138,10 +143,10 @@ module Aspera
138
143
  env_prefix = program_name.upcase + OPTION_SEP_SYMBOL
139
144
  ENV.each do |k, v|
140
145
  if k.start_with?(env_prefix)
141
- @unprocessed_env.push([k[env_prefix.length..-1].downcase.to_sym, v])
146
+ @option_pairs_env[k[env_prefix.length..-1].downcase.to_sym] = v
142
147
  end
143
148
  end
144
- Log.log.debug{"env=#{@unprocessed_env}".red}
149
+ Log.log.debug{"env=#{@option_pairs_env}".red}
145
150
  @unprocessed_cmd_line_options = []
146
151
  @unprocessed_cmd_line_arguments = []
147
152
  end
@@ -156,16 +161,18 @@ module Aspera
156
161
  until argv.empty?
157
162
  value = argv.shift
158
163
  if process_options && value.start_with?('-')
159
- if value.eql?('--')
164
+ Log.log.trace1{"opt: #{value}"}
165
+ if value.eql?(OPTIONS_STOP)
160
166
  process_options = false
161
167
  else
162
168
  @unprocessed_cmd_line_options.push(value)
163
169
  end
164
170
  else
171
+ Log.log.trace1{"arg: #{value}"}
165
172
  @unprocessed_cmd_line_arguments.push(value)
166
173
  end
167
174
  end
168
- @initial_cli_options = @unprocessed_cmd_line_options.dup
175
+ @initial_cli_options = @unprocessed_cmd_line_options.dup.freeze
169
176
  Log.log.debug{"add_cmd_line_options:commands/arguments=#{@unprocessed_cmd_line_arguments},options=#{@unprocessed_cmd_line_options}".red}
170
177
  end
171
178
 
@@ -232,6 +239,7 @@ module Aspera
232
239
  # ask interactively if requested/required
233
240
  # @param mandatory [Boolean] if true, raise error if option not set
234
241
  def get_option(option_symbol, mandatory: false, default: nil)
242
+ Aspera.assert_type(option_symbol, Symbol)
235
243
  attributes = @declared_options[option_symbol]
236
244
  Aspera.assert(attributes){"option not declared: #{option_symbol}"}
237
245
  result = nil
@@ -268,6 +276,7 @@ module Aspera
268
276
 
269
277
  # set an option value by name, either store value or call handler
270
278
  def set_option(option_symbol, value, where='code override')
279
+ Aspera.assert_type(option_symbol, Symbol)
271
280
  raise Cli::BadArgument, "Unknown option: #{option_symbol}" unless @declared_options.key?(option_symbol)
272
281
  attributes = @declared_options[option_symbol]
273
282
  Log.log.warn("#{option_symbol}: Option is deprecated: #{attributes[:deprecation]}") if attributes[:deprecation]
@@ -292,10 +301,11 @@ module Aspera
292
301
  # @param default [Object] default value
293
302
  # @param values [nil, Array, :bool, :date, :none] list of allowed values, :bool for true/false, :date for dates, :none for on/off switch
294
303
  # @param short [String] short option name
295
- # @param coerce [Class] one of the coerce types accepted par option parser
304
+ # @param coerce [Class] one of the coerce types accepted by option parser
296
305
  # @param types [Class, Array] accepted value type(s)
297
306
  # @param block [Proc] block to execute when option is found
298
307
  def declare(option_symbol, description, handler: nil, default: nil, values: nil, short: nil, coerce: nil, types: nil, deprecation: nil, &block)
308
+ Aspera.assert_type(option_symbol, Symbol)
299
309
  Aspera.assert(!@declared_options.key?(option_symbol)){"#{option_symbol} already declared"}
300
310
  Aspera.assert(description[-1] != '.'){"#{option_symbol} ends with dot"}
301
311
  Aspera.assert(description[0] == description[0].upcase){"#{option_symbol} description does not start with capital"}
@@ -307,7 +317,7 @@ module Aspera
307
317
  }
308
318
  if !types.nil?
309
319
  types = [types] unless types.is_a?(Array)
310
- Aspera.assert(types.all?(Class)){"types must be Array of Class: #{types}"}
320
+ Aspera.assert(types.all?(Class)){"types must be (Array of) Class: #{types}"}
311
321
  opt[:types] = types
312
322
  description = "#{description} (#{types.map(&:name).join(', ')})"
313
323
  end
@@ -358,7 +368,7 @@ module Aspera
358
368
  end
359
369
  when :none
360
370
  Aspera.assert(!block.nil?){"missing block for #{option_symbol}"}
361
- on_args.push(symbol_to_option(option_symbol, nil))
371
+ on_args.push(symbol_to_option(option_symbol))
362
372
  on_args.push("-#{short}") if short.is_a?(String)
363
373
  @parser.on(*on_args, &block)
364
374
  else Aspera.error_unexpected_value(values)
@@ -368,11 +378,13 @@ module Aspera
368
378
 
369
379
  # Adds each of the keys of specified hash as an option
370
380
  # @param preset_hash [Hash] hash of options to add
371
- def add_option_preset(preset_hash, op: :push)
381
+ def add_option_preset(preset_hash, where, override: true)
372
382
  Aspera.assert_type(preset_hash, Hash)
373
- Log.log.debug{"add_option_preset=#{preset_hash}"}
374
- # incremental override
375
- preset_hash.each{|k, v|@unprocessed_defaults.send(op, [k.to_sym, v])}
383
+ Log.log.debug{"add_option_preset: #{preset_hash}, #{where}, #{override}"}
384
+ preset_hash.each do |k, v|
385
+ option_symbol = k.to_sym
386
+ @option_pairs_batch[option_symbol] = v if override || !@option_pairs_batch.key?(option_symbol)
387
+ end
376
388
  end
377
389
 
378
390
  # check if there were unprocessed values to generate error
@@ -389,20 +401,20 @@ module Aspera
389
401
  end
390
402
 
391
403
  # get all original options on command line used to generate a config in config file
392
- def get_options_table(remove_from_remaining: true)
404
+ def unprocessed_options_with_value
393
405
  result = {}
394
406
  @initial_cli_options.each do |option_value|
395
407
  case option_value
396
- when /^--([^=]+)$/
408
+ when /^#{OPTION_PREFIX}([^=]+)$/o
397
409
  # ignore
398
- when /^--([^=]+)=(.*)$/
410
+ when /^#{OPTION_PREFIX}([^=]+)=(.*)$/o
399
411
  name = Regexp.last_match(1)
400
412
  value = Regexp.last_match(2)
401
413
  name.gsub!(OPTION_SEP_LINE, OPTION_SEP_SYMBOL)
402
414
  value = ExtendedValue.instance.evaluate(value)
403
415
  Log.log.debug{"option #{name}=#{value}"}
404
416
  result[name] = value
405
- @unprocessed_cmd_line_options.delete(option_value) if remove_from_remaining
417
+ @unprocessed_cmd_line_options.delete(option_value)
406
418
  else
407
419
  raise Cli::BadArgument, "wrong option format: #{option_value}"
408
420
  end
@@ -425,8 +437,8 @@ module Aspera
425
437
  def parse_options!
426
438
  Log.log.debug('parse_options!'.red)
427
439
  # first conf file, then env var
428
- apply_options_preset(@unprocessed_defaults, 'file')
429
- apply_options_preset(@unprocessed_env, 'env')
440
+ consume_option_pairs(@option_pairs_batch, 'set')
441
+ consume_option_pairs(@option_pairs_env, 'env')
430
442
  # command line override
431
443
  unknown_options = []
432
444
  begin
@@ -497,9 +509,9 @@ module Aspera
497
509
  private
498
510
 
499
511
  # generate command line option from option symbol
500
- def symbol_to_option(symbol, opt_val)
501
- result = '--' + symbol.to_s.gsub(OPTION_SEP_SYMBOL, OPTION_SEP_LINE)
502
- result = result + '=' + opt_val unless opt_val.nil?
512
+ def symbol_to_option(symbol, opt_val = nil)
513
+ result = [OPTION_PREFIX, symbol.to_s.gsub(OPTION_SEP_SYMBOL, OPTION_SEP_LINE)].join
514
+ result = [result, OPTION_VALUE_SEPARATOR, opt_val].join unless opt_val.nil?
503
515
  return result
504
516
  end
505
517
 
@@ -507,23 +519,28 @@ module Aspera
507
519
  $stdout.isatty ? value.to_s.red.bold : "[#{value}]"
508
520
  end
509
521
 
510
- def apply_options_preset(preset, where)
511
- unprocessed = []
512
- preset.each do |pair|
513
- k, v = *pair
522
+ # try to evaluate options set ib batch
523
+ # @param unprocessed_options [Array] list of options to apply (key_sym,value)
524
+ # @param where [String] where the options come from
525
+ def consume_option_pairs(unprocessed_options, where)
526
+ Log.log.debug{"consume_option_pairs: #{where}"}
527
+ options_to_set = {}
528
+ unprocessed_options.each do |k, v|
514
529
  if @declared_options.key?(k)
515
530
  # constrained parameters as string are revert to symbol
516
531
  if @declared_options[k].key?(:values) && v.is_a?(String)
517
- v = self.class.get_from_list(v, k.to_s + " in #{where}", @declared_options[k][:values])
532
+ v = self.class.get_from_list(v, "#{k} in #{where}", @declared_options[k][:values])
518
533
  end
519
- set_option(k, v, where)
534
+ options_to_set[k] = v
520
535
  else
521
- unprocessed.push(pair)
536
+ Log.log.debug{"unprocessed: #{k}: #{v}"}
522
537
  end
523
538
  end
524
- # keep only unprocessed values for next parse
525
- preset.clear
526
- preset.push(*unprocessed)
539
+ options_to_set.each do |k, v|
540
+ set_option(k, v, where)
541
+ # keep only unprocessed values for next parse
542
+ unprocessed_options.delete(k)
543
+ end
527
544
  end
528
545
  end
529
546
  end
@@ -19,6 +19,7 @@ module Aspera
19
19
  MAX_PAGES = 'pmax'
20
20
  # special identifier format: look for this name to find where supported
21
21
  REGEX_LOOKUP_ID_BY_FIELD = /^%([^:]+):(.*)$/.freeze
22
+ # instance variables, also constructor parameters
22
23
  INIT_PARAMS = %i[options transfer config formatter persistency only_manual].freeze
23
24
 
24
25
  class << self
@@ -62,15 +63,16 @@ module Aspera
62
63
  # @param description [String] description of the identifier
63
64
  # @param as_option [Symbol] option name to use if identifier is an option
64
65
  # @param block [Proc] block to search for identifier based on attribute value
65
- # @return [String] identifier
66
+ # @return [String, Array] identifier or list of ids
66
67
  def instance_identifier(description: 'identifier', as_option: nil, &block)
67
68
  if as_option.nil?
69
+ # use of option `id` is deprecated
68
70
  res_id = options.get_option(:id)
69
71
  res_id = options.get_next_argument(description) if res_id.nil?
70
72
  else
71
73
  res_id = options.get_option(as_option)
72
74
  end
73
- # cab be an Array
75
+ # can be an Array
74
76
  if res_id.is_a?(String) && (m = res_id.match(REGEX_LOOKUP_ID_BY_FIELD))
75
77
  if block
76
78
  res_id = yield(m[1], ExtendedValue.instance.evaluate(m[2]))
@@ -108,7 +110,9 @@ module Aspera
108
110
  # execute custom code
109
111
  res = yield(param)
110
112
  # if block returns a hash, let's use this (create)
111
- result = res if param.is_a?(Hash)
113
+ result = res if res.is_a?(Hash)
114
+ # TODO: remove when faspio gw api fixes this
115
+ result = res.first if res.is_a?(Array) && res.first.is_a?(Hash)
112
116
  # create -> created
113
117
  result['status'] = "#{command}#{'e' unless command.to_s.end_with?('e')}d".gsub(/yed$/, 'ied')
114
118
  rescue StandardError => e
@@ -133,9 +137,16 @@ module Aspera
133
137
  # @param item_list_key [String] result is in a sub key of the json
134
138
  # @param id_as_arg [String] if set, the id is provided as url argument ?<id_as_arg>=<id>
135
139
  # @param is_singleton [Boolean] if true, res_class_path is the full path to the resource
140
+ # @param delete_style [String] if set, the delete operation by array in payload
136
141
  # @param block [Proc] block to search for identifier based on attribute value
137
142
  # @return result suitable for CLI result
138
- def entity_command(command, rest_api, res_class_path, display_fields: nil, item_list_key: false, id_as_arg: false, is_singleton: false, &block)
143
+ def entity_command(command, rest_api, res_class_path,
144
+ display_fields: nil,
145
+ item_list_key: false,
146
+ id_as_arg: false,
147
+ is_singleton: false,
148
+ delete_style: nil,
149
+ &block)
139
150
  if is_singleton
140
151
  one_res_path = res_class_path
141
152
  elsif INSTANCE_OPS.include?(command)
@@ -152,14 +163,20 @@ module Aspera
152
163
  end
153
164
  when :delete
154
165
  raise 'cannot delete singleton' if is_singleton
166
+ if !delete_style.nil?
167
+ one_res_id = [one_res_id] unless one_res_id.is_a?(Array)
168
+ Aspera.assert_type(one_res_id, Array, exception_class: Cli::BadArgument)
169
+ rest_api.call(operation: 'DELETE', subpath: res_class_path, headers: {'Accept' => 'application/json'}, body: {delete_style => one_res_id}, body_type: :json)
170
+ return Main.result_status('deleted')
171
+ end
155
172
  return do_bulk_operation(command: command, descr: 'identifier', values: one_res_id) do |one_id|
156
- rest_api.delete("#{res_class_path}/#{one_id}", old_query_read_delete)
173
+ rest_api.delete("#{res_class_path}/#{one_id}", query_read_delete)
157
174
  {'id' => one_id}
158
175
  end
159
176
  when :show
160
177
  return {type: :single_object, data: rest_api.read(one_res_path)[:data], fields: display_fields}
161
178
  when :list
162
- resp = rest_api.read(res_class_path, old_query_read_delete)
179
+ resp = rest_api.read(res_class_path, query_read_delete)
163
180
  return Main.result_empty if resp[:http].code == '204'
164
181
  data = resp[:data]
165
182
  # TODO: not generic : which application is this for ?
@@ -215,14 +232,6 @@ module Aspera
215
232
  return query
216
233
  end
217
234
 
218
- # TODO: when deprecation of `value` is completed: remove this method, replace with query_read_delete
219
- # deprecation: 4.14
220
- def old_query_read_delete
221
- query = options.get_option(:value) # legacy, deprecated, remove, one day...
222
- query = query_read_delete if query.nil?
223
- return query
224
- end
225
-
226
235
  # TODO: when deprecation of `value` is completed: remove this method, replace with options.get_option(:query)
227
236
  # deprecation: 4.14
228
237
  def query_option(mandatory: false, default: nil)
@@ -262,6 +271,6 @@ module Aspera
262
271
  end
263
272
  return value
264
273
  end
265
- end # Plugin
266
- end # Cli
267
- end # Aspera
274
+ end
275
+ end
276
+ end
@@ -6,34 +6,25 @@ module Aspera
6
6
  # option is retrieved from another object using accessor
7
7
  class PluginFactory
8
8
  include Singleton
9
- attr_reader :lookup_folders, :plugins
10
9
 
11
10
  RUBY_FILE_EXT = '.rb'
12
11
  PLUGINS_MODULE = 'Plugins'
13
- private_constant :RUBY_FILE_EXT
14
- class << self
15
- # instantiate a plugin
16
- # plugins must be Capitalized
17
- def plugin_class(plugin_name_sym)
18
- # Module.nesting[2] is Cli::Plugins
19
- return Object.const_get("#{Module.nesting[2]}::#{PLUGINS_MODULE}::#{plugin_name_sym.to_s.capitalize}")
20
- end
21
- end
12
+ private_constant :RUBY_FILE_EXT, :PLUGINS_MODULE
13
+
14
+ attr_reader :lookup_folders
22
15
 
23
16
  def initialize
24
17
  @lookup_folders = []
18
+ # information on plugins
25
19
  @plugins = {}
26
20
  end
27
21
 
28
- def add_plugin_info(path)
29
- raise "ERROR: plugin path must end with #{RUBY_FILE_EXT}" if !path.end_with?(RUBY_FILE_EXT)
30
- plugin_symbol = File.basename(path, RUBY_FILE_EXT).to_sym
31
- req = path.sub(/#{RUBY_FILE_EXT}$/o, '')
32
- if @plugins.key?(plugin_symbol)
33
- Log.log.warn{"skipping plugin already registered: #{plugin_symbol}"}
34
- return
35
- end
36
- @plugins[plugin_symbol] = {source: path, require_stanza: req}
22
+ def plugin_list
23
+ @plugins.keys
24
+ end
25
+
26
+ def plugin_source(plugin_name_sym)
27
+ @plugins[plugin_name_sym][:source]
37
28
  end
38
29
 
39
30
  def add_lookup_folder(folder)
@@ -52,9 +43,29 @@ module Aspera
52
43
  end
53
44
  end
54
45
 
46
+ def plugin_class(plugin_name_sym)
47
+ raise "ERROR: plugin not found: #{plugin_name_sym}" unless @plugins.key?(plugin_name_sym)
48
+ require @plugins[plugin_name_sym][:require_stanza]
49
+ # Module.nesting[1] is Aspera::Cli
50
+ return Object.const_get("#{Module.nesting[1]}::#{PLUGINS_MODULE}::#{plugin_name_sym.to_s.capitalize}")
51
+ end
52
+
55
53
  def create(plugin_name_sym, **args)
56
54
  # TODO: check that ancestor is Plugin?
57
- self.class.plugin_class(plugin_name_sym).new(**args)
55
+ plugin_class(plugin_name_sym).new(**args)
56
+ end
57
+
58
+ private
59
+
60
+ def add_plugin_info(path)
61
+ raise "ERROR: plugin path must end with #{RUBY_FILE_EXT}" if !path.end_with?(RUBY_FILE_EXT)
62
+ plugin_symbol = File.basename(path, RUBY_FILE_EXT).to_sym
63
+ req = path.sub(/#{RUBY_FILE_EXT}$/o, '')
64
+ if @plugins.key?(plugin_symbol)
65
+ Log.log.warn{"skipping plugin already registered: #{plugin_symbol}"}
66
+ return
67
+ end
68
+ @plugins[plugin_symbol] = {source: path, require_stanza: req}
58
69
  end
59
70
  end
60
71
  end
@@ -1,20 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'aspera/api/aoc'
4
+ require 'aspera/nagios'
4
5
 
5
6
  module Aspera
6
7
  module Cli
7
8
  module Plugins
8
9
  class Alee < Cli::BasicAuthPlugin
9
- ACTIONS = %i[entitlement].freeze
10
+ ACTIONS = %i[health entitlement].freeze
10
11
 
11
12
  def execute_action
12
13
  command = options.get_next_command(ACTIONS)
13
14
  case command
15
+ when :health
16
+ nagios = Nagios.new
17
+ begin
18
+ api = Api::Alee.new(nil, nil, version: 'ping')
19
+ result = api.call(operation: 'GET', subpath: '')
20
+ raise "unexpected response: #{result[:http].body}" unless result[:http].body.eql?('pong')
21
+ nagios.add_ok('api', 'answered ok')
22
+ rescue StandardError => e
23
+ nagios.add_critical('api', e.to_s)
24
+ end
25
+ return nagios.result
14
26
  when :entitlement
15
27
  entitlement_id = options.get_option(:username, mandatory: true)
16
28
  customer_id = options.get_option(:password, mandatory: true)
17
- api_metering = Api::AoC.metering_api(entitlement_id, customer_id)
29
+ api_metering = Api::Alee.new(entitlement_id, customer_id)
18
30
  return {type: :single_object, data: api_metering.read('entitlement')[:data]}
19
31
  end
20
32
  end