aspera-cli 4.15.0 → 4.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/BUGS.md +29 -3
- data/CHANGELOG.md +375 -280
- data/CONTRIBUTING.md +71 -18
- data/README.md +1978 -1656
- data/bin/ascli +13 -31
- data/bin/asession +32 -22
- data/examples/dascli +2 -2
- data/lib/aspera/agent/alpha.rb +117 -0
- data/lib/aspera/agent/base.rb +61 -0
- data/lib/aspera/{fasp/agent_connect.rb → agent/connect.rb} +13 -11
- data/lib/aspera/{fasp/agent_direct.rb → agent/direct.rb} +116 -116
- data/lib/aspera/{fasp/agent_httpgw.rb → agent/httpgw.rb} +21 -19
- data/lib/aspera/{fasp/agent_node.rb → agent/node.rb} +21 -33
- data/lib/aspera/agent/trsdk.rb +188 -0
- data/lib/aspera/api/aoc.rb +586 -0
- data/lib/aspera/api/ats.rb +46 -0
- data/lib/aspera/api/cos_node.rb +95 -0
- data/lib/aspera/api/node.rb +344 -0
- data/lib/aspera/ascmd.rb +47 -14
- data/lib/aspera/{fasp → ascp}/installation.rb +54 -15
- data/lib/aspera/{fasp → ascp}/management.rb +14 -14
- data/lib/aspera/{fasp → ascp}/products.rb +1 -1
- data/lib/aspera/assert.rb +45 -0
- data/lib/aspera/cli/basic_auth_plugin.rb +11 -10
- data/lib/aspera/cli/extended_value.rb +5 -5
- data/lib/aspera/cli/formatter.rb +27 -14
- data/lib/aspera/cli/hints.rb +7 -6
- data/lib/aspera/cli/main.rb +49 -29
- data/lib/aspera/cli/manager.rb +46 -36
- data/lib/aspera/cli/plugin.rb +34 -20
- data/lib/aspera/cli/plugin_factory.rb +61 -0
- data/lib/aspera/cli/plugins/alee.rb +7 -7
- data/lib/aspera/cli/plugins/aoc.rb +168 -132
- data/lib/aspera/cli/plugins/ats.rb +33 -33
- data/lib/aspera/cli/plugins/bss.rb +3 -4
- data/lib/aspera/cli/plugins/config.rb +250 -272
- data/lib/aspera/cli/plugins/console.rb +8 -6
- data/lib/aspera/cli/plugins/cos.rb +20 -19
- data/lib/aspera/cli/plugins/faspex.rb +71 -60
- data/lib/aspera/cli/plugins/faspex5.rb +212 -133
- data/lib/aspera/cli/plugins/node.rb +83 -75
- data/lib/aspera/cli/plugins/orchestrator.rb +36 -44
- data/lib/aspera/cli/plugins/preview.rb +33 -31
- data/lib/aspera/cli/plugins/server.rb +33 -32
- data/lib/aspera/cli/plugins/shares.rb +39 -33
- data/lib/aspera/cli/sync_actions.rb +9 -9
- data/lib/aspera/cli/transfer_agent.rb +45 -25
- data/lib/aspera/cli/transfer_progress.rb +2 -3
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +5 -0
- data/lib/aspera/command_line_builder.rb +16 -14
- data/lib/aspera/coverage.rb +21 -0
- data/lib/aspera/data_repository.rb +33 -2
- data/lib/aspera/environment.rb +5 -4
- data/lib/aspera/faspex_gw.rb +13 -11
- data/lib/aspera/faspex_postproc.rb +6 -5
- data/lib/aspera/id_generator.rb +4 -2
- data/lib/aspera/json_rpc.rb +10 -8
- data/lib/aspera/keychain/encrypted_hash.rb +46 -11
- data/lib/aspera/keychain/macos_security.rb +29 -22
- data/lib/aspera/log.rb +5 -4
- data/lib/aspera/nagios.rb +7 -2
- data/lib/aspera/node_simulator.rb +213 -0
- data/lib/aspera/oauth/base.rb +143 -0
- data/lib/aspera/oauth/factory.rb +124 -0
- data/lib/aspera/oauth/generic.rb +34 -0
- data/lib/aspera/oauth/jwt.rb +51 -0
- data/lib/aspera/oauth/url_json.rb +31 -0
- data/lib/aspera/oauth/web.rb +50 -0
- data/lib/aspera/oauth.rb +5 -328
- data/lib/aspera/open_application.rb +7 -7
- data/lib/aspera/persistency_action_once.rb +13 -14
- data/lib/aspera/persistency_folder.rb +3 -2
- data/lib/aspera/preview/file_types.rb +53 -267
- data/lib/aspera/preview/generator.rb +7 -5
- data/lib/aspera/preview/terminal.rb +17 -7
- data/lib/aspera/preview/utils.rb +8 -7
- data/lib/aspera/proxy_auto_config.rb +6 -3
- data/lib/aspera/rest.rb +187 -140
- data/lib/aspera/rest_error_analyzer.rb +1 -0
- data/lib/aspera/rest_errors_aspera.rb +5 -3
- data/lib/aspera/resumer.rb +77 -0
- data/lib/aspera/secret_hider.rb +5 -2
- data/lib/aspera/ssh.rb +15 -8
- data/lib/aspera/temp_file_manager.rb +1 -1
- data/lib/aspera/{fasp → transfer}/error.rb +3 -3
- data/lib/aspera/{fasp → transfer}/error_info.rb +1 -1
- data/lib/aspera/{fasp → transfer}/faux_file.rb +1 -1
- data/lib/aspera/{fasp → transfer}/parameters.rb +95 -120
- data/lib/aspera/{fasp/transfer_spec.rb → transfer/spec.rb} +23 -19
- data/lib/aspera/{fasp/parameters.yaml → transfer/spec.yaml} +4 -99
- data/lib/aspera/transfer/sync.rb +273 -0
- data/lib/aspera/{fasp → transfer}/uri.rb +10 -9
- data/lib/aspera/web_server_simple.rb +12 -3
- data.tar.gz.sig +0 -0
- metadata +92 -68
- metadata.gz.sig +0 -0
- data/lib/aspera/aoc.rb +0 -606
- data/lib/aspera/ats_api.rb +0 -47
- data/lib/aspera/cos_node.rb +0 -93
- data/lib/aspera/fasp/agent_aspera.rb +0 -126
- data/lib/aspera/fasp/agent_base.rb +0 -48
- data/lib/aspera/fasp/agent_trsdk.rb +0 -146
- data/lib/aspera/fasp/resume_policy.rb +0 -77
- data/lib/aspera/node.rb +0 -338
- data/lib/aspera/sync.rb +0 -219
data/lib/aspera/cli/manager.rb
CHANGED
|
@@ -5,6 +5,7 @@ require 'aspera/cli/error'
|
|
|
5
5
|
require 'aspera/colors'
|
|
6
6
|
require 'aspera/secret_hider'
|
|
7
7
|
require 'aspera/log'
|
|
8
|
+
require 'aspera/assert'
|
|
8
9
|
require 'io/console'
|
|
9
10
|
require 'optparse'
|
|
10
11
|
|
|
@@ -20,7 +21,7 @@ module Aspera
|
|
|
20
21
|
@option_name = option_name
|
|
21
22
|
@has_writer = @object.respond_to?(writer_method)
|
|
22
23
|
Log.log.debug{"AttrAccessor: #{@option_name}: #{@object.class}.#{@method}: writer=#{@has_writer}"}
|
|
23
|
-
|
|
24
|
+
Aspera.assert(@object.respond_to?(@method)) {"#{object} does not respond to #{method_name}"}
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
def value
|
|
@@ -54,12 +55,13 @@ module Aspera
|
|
|
54
55
|
# option name separator in code (symbol)
|
|
55
56
|
OPTION_SEP_SYMBOL = '_'
|
|
56
57
|
SOURCE_USER = 'cmdline' # cspell:disable-line
|
|
58
|
+
TYPE_INTEGER = [Integer].freeze
|
|
57
59
|
|
|
58
|
-
private_constant :FALSE_VALUES, :TRUE_VALUES, :BOOLEAN_VALUES, :OPTION_SEP_LINE, :OPTION_SEP_SYMBOL, :SOURCE_USER
|
|
60
|
+
private_constant :FALSE_VALUES, :TRUE_VALUES, :BOOLEAN_VALUES, :OPTION_SEP_LINE, :OPTION_SEP_SYMBOL, :SOURCE_USER, :TYPE_INTEGER
|
|
59
61
|
|
|
60
62
|
class << self
|
|
61
63
|
def enum_to_bool(enum)
|
|
62
|
-
|
|
64
|
+
Aspera.assert_values(enum, BOOLEAN_VALUES){'boolean'}
|
|
63
65
|
return TRUE_VALUES.include?(enum)
|
|
64
66
|
end
|
|
65
67
|
|
|
@@ -73,14 +75,17 @@ module Aspera
|
|
|
73
75
|
matching_exact = allowed_values.select{|i| i.to_s.eql?(short_value)}
|
|
74
76
|
return matching_exact.first if matching_exact.length == 1
|
|
75
77
|
matching = allowed_values.select{|i| i.to_s.start_with?(short_value)}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
multi_choice_assert(!matching.empty?, "unknown value for #{descr}: #{short_value}", allowed_values)
|
|
79
|
+
multi_choice_assert(matching.length.eql?(1), "ambiguous shortcut for #{descr}: #{short_value}", matching)
|
|
78
80
|
return enum_to_bool(matching.first) if allowed_values.eql?(BOOLEAN_VALUES)
|
|
79
81
|
return matching.first
|
|
80
82
|
end
|
|
81
83
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
+
# Generates error message with list of allowed values
|
|
85
|
+
# @param error_msg [String] error message
|
|
86
|
+
# @param choices [Array] list of allowed values
|
|
87
|
+
def multi_choice_assert(assertion, error_msg, choices)
|
|
88
|
+
raise Cli::BadArgument, [error_msg, 'Use:'].concat(choices.map{|c|"- #{c}"}.sort).join("\n") unless assertion
|
|
84
89
|
end
|
|
85
90
|
|
|
86
91
|
# change option name with dash to name with underscore
|
|
@@ -92,9 +97,13 @@ module Aspera
|
|
|
92
97
|
return "--#{name.to_s.gsub(OPTION_SEP_SYMBOL, OPTION_SEP_LINE)}"
|
|
93
98
|
end
|
|
94
99
|
|
|
100
|
+
# @param what [Symbol] :option or :argument
|
|
101
|
+
# @param descr [String] description for help
|
|
102
|
+
# @param value [Object] value to check
|
|
103
|
+
# @param type_list [NilClass, Class, Array[Class]] accepted value type(s)
|
|
95
104
|
def validate_type(what, descr, value, type_list)
|
|
96
105
|
return nil if type_list.nil?
|
|
97
|
-
|
|
106
|
+
Aspera.assert(type_list.is_a?(Array) && type_list.all?(Class)){'types must be a Class Array'}
|
|
98
107
|
raise Cli::BadArgument,
|
|
99
108
|
"#{what.to_s.capitalize} #{descr} is a #{value.class} but must be #{type_list.length > 1 ? 'one of ' : ''}#{type_list.map(&:name).join(',')}" unless \
|
|
100
109
|
type_list.any?{|t|value.is_a?(t)}
|
|
@@ -172,10 +181,15 @@ module Aspera
|
|
|
172
181
|
# @param default [Object] default value
|
|
173
182
|
# @return value, list or nil
|
|
174
183
|
def get_next_argument(descr, expected: :single, mandatory: true, type: nil, aliases: nil, default: nil)
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
184
|
+
Aspera.assert(%i[single multiple].include?(expected) || (expected.is_a?(Array) && expected.all?(Symbol))) do
|
|
185
|
+
'expected must be single, multiple, or array of symbol'
|
|
186
|
+
end
|
|
187
|
+
Aspera.assert(type.nil? || type.is_a?(Class) || (type.is_a?(Array) && type.all?(Class))){'type must be Class or Array of Class'}
|
|
188
|
+
Aspera.assert(aliases.nil? || (aliases.is_a?(Hash) && aliases.keys.all?(Symbol) && aliases.values.all?(Symbol))){'aliases must be Hash'}
|
|
189
|
+
allowed_types = type
|
|
190
|
+
unless allowed_types.nil?
|
|
191
|
+
allowed_types = [allowed_types] unless allowed_types.is_a?(Array)
|
|
192
|
+
descr = "#{descr} (#{allowed_types.join(', ')})"
|
|
179
193
|
end
|
|
180
194
|
result =
|
|
181
195
|
if !@unprocessed_cmd_line_arguments.empty?
|
|
@@ -193,23 +207,21 @@ module Aspera
|
|
|
193
207
|
when Array
|
|
194
208
|
allowed_values = [].concat(expected)
|
|
195
209
|
allowed_values.concat(aliases.keys) unless aliases.nil?
|
|
196
|
-
raise "internal error: only symbols allowed: #{allowed_values}" unless allowed_values.all?(Symbol)
|
|
197
210
|
self.class.get_from_list(@unprocessed_cmd_line_arguments.shift, descr, allowed_values)
|
|
198
|
-
else
|
|
199
|
-
raise 'Internal error: expected: must be single, multiple, or value array'
|
|
211
|
+
else Aspera.error_unexpected_value(expected)
|
|
200
212
|
end
|
|
201
213
|
elsif !default.nil? then default
|
|
202
214
|
# no value provided, either get value interactively, or exception
|
|
203
215
|
elsif mandatory then get_interactive(:argument, descr, expected: expected)
|
|
204
216
|
end
|
|
205
|
-
if result.is_a?(String) &&
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
217
|
+
if result.is_a?(String) && allowed_types.eql?(TYPE_INTEGER)
|
|
218
|
+
int_result = Integer(result, exception: false)
|
|
219
|
+
raise Cli::BadArgument, "Invalid integer: #{result}" if int_result.nil?
|
|
220
|
+
result = int_result
|
|
209
221
|
end
|
|
210
222
|
Log.log.debug{"#{descr}=#{result}"}
|
|
211
|
-
result = aliases[result] if
|
|
212
|
-
self.class.validate_type(:argument, descr, result,
|
|
223
|
+
result = aliases[result] if aliases&.key?(result)
|
|
224
|
+
self.class.validate_type(:argument, descr, result, allowed_types) unless result.nil? && !mandatory
|
|
213
225
|
return result
|
|
214
226
|
end
|
|
215
227
|
|
|
@@ -221,7 +233,7 @@ module Aspera
|
|
|
221
233
|
# @param mandatory [Boolean] if true, raise error if option not set
|
|
222
234
|
def get_option(option_symbol, mandatory: false, default: nil)
|
|
223
235
|
attributes = @declared_options[option_symbol]
|
|
224
|
-
|
|
236
|
+
Aspera.assert(attributes){"option not declared: #{option_symbol}"}
|
|
225
237
|
result = nil
|
|
226
238
|
case attributes[:read_write]
|
|
227
239
|
when :accessor
|
|
@@ -284,12 +296,10 @@ module Aspera
|
|
|
284
296
|
# @param types [Class, Array] accepted value type(s)
|
|
285
297
|
# @param block [Proc] block to execute when option is found
|
|
286
298
|
def declare(option_symbol, description, handler: nil, default: nil, values: nil, short: nil, coerce: nil, types: nil, deprecation: nil, &block)
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
raise "INTERNAL ERROR: #{option_symbol} description does not start with capital" unless description[0] == description[0].upcase
|
|
292
|
-
raise "INTERNAL ERROR: #{option_symbol} shall use :types" if ['hash', 'extended value'].any?{|s|description.downcase.include?(s) }
|
|
299
|
+
Aspera.assert(!@declared_options.key?(option_symbol)){"#{option_symbol} already declared"}
|
|
300
|
+
Aspera.assert(description[-1] != '.'){"#{option_symbol} ends with dot"}
|
|
301
|
+
Aspera.assert(description[0] == description[0].upcase){"#{option_symbol} description does not start with capital"}
|
|
302
|
+
Aspera.assert(!['hash', 'extended value'].any?{|s|description.downcase.include?(s) }){"#{option_symbol} shall use :types"}
|
|
293
303
|
opt = @declared_options[option_symbol] = {
|
|
294
304
|
read_write: handler.nil? ? :value : :accessor,
|
|
295
305
|
# by default passwords and secrets are sensitive, else specify when declaring the option
|
|
@@ -297,7 +307,7 @@ module Aspera
|
|
|
297
307
|
}
|
|
298
308
|
if !types.nil?
|
|
299
309
|
types = [types] unless types.is_a?(Array)
|
|
300
|
-
|
|
310
|
+
Aspera.assert(types.all?(Class)){"types must be Array of Class: #{types}"}
|
|
301
311
|
opt[:types] = types
|
|
302
312
|
description = "#{description} (#{types.map(&:name).join(', ')})"
|
|
303
313
|
end
|
|
@@ -307,8 +317,8 @@ module Aspera
|
|
|
307
317
|
end
|
|
308
318
|
Log.log.debug{"declare: #{option_symbol}: #{opt[:read_write]}".green}
|
|
309
319
|
if opt[:read_write].eql?(:accessor)
|
|
310
|
-
|
|
311
|
-
|
|
320
|
+
Aspera.assert_type(handler, Hash)
|
|
321
|
+
Aspera.assert(handler.keys.sort.eql?(%i[m o]))
|
|
312
322
|
Log.log.debug{"set attr obj #{option_symbol} (#{handler[:o]},#{handler[:m]})"}
|
|
313
323
|
opt[:accessor] = AttrAccessor.new(handler[:o], handler[:m], option_symbol)
|
|
314
324
|
end
|
|
@@ -347,11 +357,11 @@ module Aspera
|
|
|
347
357
|
set_option(option_symbol, time_string, SOURCE_USER)
|
|
348
358
|
end
|
|
349
359
|
when :none
|
|
350
|
-
|
|
360
|
+
Aspera.assert(!block.nil?){"missing block for #{option_symbol}"}
|
|
351
361
|
on_args.push(symbol_to_option(option_symbol, nil))
|
|
352
362
|
on_args.push("-#{short}") if short.is_a?(String)
|
|
353
363
|
@parser.on(*on_args, &block)
|
|
354
|
-
else
|
|
364
|
+
else Aspera.error_unexpected_value(values)
|
|
355
365
|
end
|
|
356
366
|
Log.log.debug{"on_args=#{on_args}"}
|
|
357
367
|
end
|
|
@@ -359,8 +369,8 @@ module Aspera
|
|
|
359
369
|
# Adds each of the keys of specified hash as an option
|
|
360
370
|
# @param preset_hash [Hash] hash of options to add
|
|
361
371
|
def add_option_preset(preset_hash, op: :push)
|
|
372
|
+
Aspera.assert_type(preset_hash, Hash)
|
|
362
373
|
Log.log.debug{"add_option_preset=#{preset_hash}"}
|
|
363
|
-
raise "internal error: default expects Hash: #{preset_hash.class}" unless preset_hash.is_a?(Hash)
|
|
364
374
|
# incremental override
|
|
365
375
|
preset_hash.each{|k, v|@unprocessed_defaults.send(op, [k.to_sym, v])}
|
|
366
376
|
end
|
|
@@ -460,8 +470,8 @@ module Aspera
|
|
|
460
470
|
|
|
461
471
|
def get_interactive(type, descr, expected: :single)
|
|
462
472
|
if !@ask_missing_mandatory
|
|
463
|
-
raise Cli::BadArgument,
|
|
464
|
-
|
|
473
|
+
raise Cli::BadArgument, "missing argument (#{expected}): #{descr}" unless expected.is_a?(Array)
|
|
474
|
+
self.class.multi_choice_assert(false, "missing: #{descr}", expected)
|
|
465
475
|
end
|
|
466
476
|
result = nil
|
|
467
477
|
sensitive = type.eql?(:option) && @declared_options[descr.to_sym].is_a?(Hash) && @declared_options[descr.to_sym][:sensitive]
|
data/lib/aspera/cli/plugin.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'aspera/cli/extended_value'
|
|
4
|
+
require 'aspera/assert'
|
|
4
5
|
|
|
5
6
|
module Aspera
|
|
6
7
|
module Cli
|
|
@@ -18,6 +19,7 @@ module Aspera
|
|
|
18
19
|
MAX_PAGES = 'pmax'
|
|
19
20
|
# special identifier format: look for this name to find where supported
|
|
20
21
|
REGEX_LOOKUP_ID_BY_FIELD = /^%([^:]+):(.*)$/.freeze
|
|
22
|
+
INIT_PARAMS = %i[options transfer config formatter persistency only_manual].freeze
|
|
21
23
|
|
|
22
24
|
class << self
|
|
23
25
|
def declare_generic_options(options)
|
|
@@ -32,12 +34,18 @@ module Aspera
|
|
|
32
34
|
end
|
|
33
35
|
end
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
attr_accessor(*INIT_PARAMS)
|
|
38
|
+
|
|
39
|
+
def initialize(options:, transfer:, config:, formatter:, persistency:, only_manual:)
|
|
40
|
+
@options = options
|
|
41
|
+
@transfer = transfer
|
|
42
|
+
@config = config
|
|
43
|
+
@formatter = formatter
|
|
44
|
+
@persistency = persistency
|
|
45
|
+
@only_manual = only_manual
|
|
38
46
|
# check presence in descendant of mandatory method and constant
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
Aspera.assert(respond_to?(:execute_action)){"Missing method 'execute_action' in #{self.class}"}
|
|
48
|
+
Aspera.assert(self.class.constants.include?(:ACTIONS)){'ACTIONS shall be redefined by subclass'}
|
|
41
49
|
# manual header for all plugins
|
|
42
50
|
options.parser.separator('')
|
|
43
51
|
options.parser.separator("COMMAND: #{self.class.name.split('::').last.downcase}")
|
|
@@ -45,6 +53,11 @@ module Aspera
|
|
|
45
53
|
options.parser.separator('OPTIONS:')
|
|
46
54
|
end
|
|
47
55
|
|
|
56
|
+
def init_params
|
|
57
|
+
# return a hash of instance variables
|
|
58
|
+
INIT_PARAMS.map{|p| [p, instance_variable_get("@#{p}".to_sym)]}.to_h
|
|
59
|
+
end
|
|
60
|
+
|
|
48
61
|
# must be called AFTER the instance action, ... folder browse <call instance_identifier>
|
|
49
62
|
# @param description [String] description of the identifier
|
|
50
63
|
# @param as_option [Symbol] option name to use if identifier is an option
|
|
@@ -75,6 +88,7 @@ module Aspera
|
|
|
75
88
|
# @param id_result [String] key in result hash to use as identifier
|
|
76
89
|
# @param fields [Array] fields to display
|
|
77
90
|
def do_bulk_operation(command:, descr:, values: Hash, id_result: 'id', fields: :default)
|
|
91
|
+
Aspera.assert(block_given?){'missing block'}
|
|
78
92
|
is_bulk = options.get_option(:bulk)
|
|
79
93
|
case values
|
|
80
94
|
when :identifier
|
|
@@ -82,7 +96,6 @@ module Aspera
|
|
|
82
96
|
when Class
|
|
83
97
|
values = value_create_modify(command: command, type: values, bulk: is_bulk)
|
|
84
98
|
end
|
|
85
|
-
raise 'Internal error: missing block' unless block_given?
|
|
86
99
|
# if not bulk, there is a single value
|
|
87
100
|
params = is_bulk ? values : [values]
|
|
88
101
|
Log.log.warn('Empty list given for bulk operation') if params.empty?
|
|
@@ -147,6 +160,7 @@ module Aspera
|
|
|
147
160
|
return {type: :single_object, data: rest_api.read(one_res_path)[:data], fields: display_fields}
|
|
148
161
|
when :list
|
|
149
162
|
resp = rest_api.read(res_class_path, old_query_read_delete)
|
|
163
|
+
return Main.result_empty if resp[:http].code == '204'
|
|
150
164
|
data = resp[:data]
|
|
151
165
|
# TODO: not generic : which application is this for ?
|
|
152
166
|
if resp[:http]['Content-Type'].start_with?('application/vnd.api+json')
|
|
@@ -180,10 +194,10 @@ module Aspera
|
|
|
180
194
|
end
|
|
181
195
|
|
|
182
196
|
# implement generic rest operations on given resource path
|
|
183
|
-
def entity_action(rest_api, res_class_path, **opts)
|
|
197
|
+
def entity_action(rest_api, res_class_path, **opts, &block)
|
|
184
198
|
# res_name=res_class_path.gsub(%r{^.*/},'').gsub(%r{s$},'').gsub('_',' ')
|
|
185
199
|
command = options.get_next_command(ALL_OPS)
|
|
186
|
-
return entity_command(command, rest_api, res_class_path, **opts)
|
|
200
|
+
return entity_command(command, rest_api, res_class_path, **opts, &block)
|
|
187
201
|
end
|
|
188
202
|
|
|
189
203
|
# query parameters in URL suitable for REST list/GET and delete/DELETE
|
|
@@ -223,31 +237,31 @@ module Aspera
|
|
|
223
237
|
|
|
224
238
|
# Retrieves an extended value from command line, used for creation or modification of entities
|
|
225
239
|
# @param command [Symbol] command name for error message
|
|
226
|
-
# @param type [Class] expected type of value, either a Class, an Array of Class
|
|
240
|
+
# @param type [Class] expected type of value, either a Class, an Array of Class
|
|
241
|
+
# @param bulk [Boolean] if true, value must be an Array of <type>
|
|
227
242
|
# @param default [Object] default value if not provided
|
|
228
243
|
# TODO: when deprecation of `value` is completed: remove line with :value
|
|
229
|
-
def value_create_modify(command:, type: Hash, bulk: false, default: nil)
|
|
244
|
+
def value_create_modify(command:, description: nil, type: Hash, bulk: false, default: nil)
|
|
230
245
|
value = options.get_option(:value)
|
|
231
246
|
Log.log.warn("option `value` is deprecated. Use positional parameter for #{command}") unless value.nil?
|
|
232
|
-
value = options.get_next_argument(
|
|
247
|
+
value = options.get_next_argument(
|
|
248
|
+
"parameters for #{command}#{description.nil? ? '' : " (#{description})"}", mandatory: default.nil?,
|
|
249
|
+
type: bulk ? Array : type) if value.nil?
|
|
233
250
|
value = default if value.nil?
|
|
234
251
|
unless type.nil?
|
|
235
252
|
type = [type] unless type.is_a?(Array)
|
|
236
|
-
|
|
253
|
+
Aspera.assert(type.all?(Class)){"check types must be a Class, not #{type.map(&:class).join(',')}"}
|
|
237
254
|
if bulk
|
|
238
|
-
|
|
239
|
-
|
|
255
|
+
Aspera.assert_type(value, Array, exception_class: Cli::BadArgument)
|
|
256
|
+
value.each do |v|
|
|
257
|
+
Aspera.assert_values(v.class, type, exception_class: Cli::BadArgument)
|
|
258
|
+
end
|
|
240
259
|
else
|
|
241
|
-
|
|
260
|
+
Aspera.assert_values(value.class, type, exception_class: Cli::BadArgument)
|
|
242
261
|
end
|
|
243
262
|
end
|
|
244
263
|
return value
|
|
245
264
|
end
|
|
246
|
-
|
|
247
|
-
# shortcuts helpers for plugin environment
|
|
248
|
-
%i[options transfer config formatter persistency].each do |name|
|
|
249
|
-
define_method(name){@agents[name]}
|
|
250
|
-
end
|
|
251
265
|
end # Plugin
|
|
252
266
|
end # Cli
|
|
253
267
|
end # Aspera
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'singleton'
|
|
4
|
+
module Aspera
|
|
5
|
+
module Cli
|
|
6
|
+
# option is retrieved from another object using accessor
|
|
7
|
+
class PluginFactory
|
|
8
|
+
include Singleton
|
|
9
|
+
attr_reader :lookup_folders, :plugins
|
|
10
|
+
|
|
11
|
+
RUBY_FILE_EXT = '.rb'
|
|
12
|
+
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
|
|
22
|
+
|
|
23
|
+
def initialize
|
|
24
|
+
@lookup_folders = []
|
|
25
|
+
@plugins = {}
|
|
26
|
+
end
|
|
27
|
+
|
|
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}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def add_lookup_folder(folder)
|
|
40
|
+
@lookup_folders.unshift(folder)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# find plugins in defined paths
|
|
44
|
+
def add_plugins_from_lookup_folders
|
|
45
|
+
@lookup_folders.each do |folder|
|
|
46
|
+
next unless File.directory?(folder)
|
|
47
|
+
# TODO: add gem root to load path ? and require short folder ?
|
|
48
|
+
# $LOAD_PATH.push(folder) if i[:add_path]
|
|
49
|
+
Dir.entries(folder).select{|file|file.end_with?(RUBY_FILE_EXT)}.each do |source|
|
|
50
|
+
add_plugin_info(File.join(folder, source))
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def create(plugin_name_sym, **args)
|
|
56
|
+
# TODO: check that ancestor is Plugin?
|
|
57
|
+
self.class.plugin_class(plugin_name_sym).new(**args)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'aspera/aoc'
|
|
3
|
+
require 'aspera/api/aoc'
|
|
4
4
|
|
|
5
5
|
module Aspera
|
|
6
6
|
module Cli
|
|
7
7
|
module Plugins
|
|
8
|
-
class Alee <
|
|
8
|
+
class Alee < Cli::BasicAuthPlugin
|
|
9
9
|
ACTIONS = %i[entitlement].freeze
|
|
10
10
|
|
|
11
11
|
def execute_action
|
|
@@ -14,11 +14,11 @@ module Aspera
|
|
|
14
14
|
when :entitlement
|
|
15
15
|
entitlement_id = options.get_option(:username, mandatory: true)
|
|
16
16
|
customer_id = options.get_option(:password, mandatory: true)
|
|
17
|
-
api_metering = AoC.metering_api(entitlement_id, customer_id)
|
|
17
|
+
api_metering = Api::AoC.metering_api(entitlement_id, customer_id)
|
|
18
18
|
return {type: :single_object, data: api_metering.read('entitlement')[:data]}
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|