aspera-cli 4.18.0 → 4.18.1
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 +3 -2
- data/CHANGELOG.md +10 -0
- data/README.md +96 -59
- data/examples/build_package.sh +28 -0
- data/lib/aspera/agent/alpha.rb +4 -4
- data/lib/aspera/agent/connect.rb +3 -4
- data/lib/aspera/agent/httpgw.rb +1 -1
- data/lib/aspera/api/httpgw.rb +4 -1
- data/lib/aspera/api/node.rb +110 -77
- data/lib/aspera/ascp/products.rb +1 -1
- data/lib/aspera/cli/extended_value.rb +27 -14
- data/lib/aspera/cli/formatter.rb +11 -10
- data/lib/aspera/cli/main.rb +11 -11
- data/lib/aspera/cli/manager.rb +99 -84
- data/lib/aspera/cli/plugin.rb +2 -5
- data/lib/aspera/cli/plugins/aoc.rb +15 -14
- data/lib/aspera/cli/plugins/config.rb +20 -19
- data/lib/aspera/cli/plugins/faspex.rb +5 -4
- data/lib/aspera/cli/plugins/faspex5.rb +16 -13
- data/lib/aspera/cli/plugins/node.rb +46 -38
- data/lib/aspera/cli/plugins/orchestrator.rb +3 -2
- data/lib/aspera/cli/plugins/preview.rb +1 -1
- data/lib/aspera/cli/plugins/server.rb +1 -1
- data/lib/aspera/cli/special_values.rb +13 -0
- data/lib/aspera/cli/sync_actions.rb +4 -4
- data/lib/aspera/cli/transfer_agent.rb +2 -2
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/environment.rb +64 -4
- data/lib/aspera/oauth/web.rb +2 -2
- data/lib/aspera/rest.rb +46 -15
- data.tar.gz.sig +0 -0
- metadata +4 -3
- metadata.gz.sig +0 -0
- data/lib/aspera/open_application.rb +0 -69
data/lib/aspera/cli/manager.rb
CHANGED
@@ -55,12 +55,13 @@ module Aspera
|
|
55
55
|
# option name separator in code (symbol)
|
56
56
|
OPTION_SEP_SYMBOL = '_'
|
57
57
|
SOURCE_USER = 'cmdline' # cspell:disable-line
|
58
|
-
TYPE_INTEGER = [Integer].freeze
|
59
58
|
OPTION_VALUE_SEPARATOR = '='
|
60
59
|
OPTION_PREFIX = '--'
|
61
60
|
OPTIONS_STOP = '--'
|
62
61
|
|
63
|
-
|
62
|
+
DEFAULT_PARSER_TYPES = [Array, Hash].freeze
|
63
|
+
|
64
|
+
private_constant :FALSE_VALUES, :TRUE_VALUES, :BOOLEAN_VALUES, :OPTION_SEP_LINE, :OPTION_SEP_SYMBOL, :SOURCE_USER
|
64
65
|
|
65
66
|
class << self
|
66
67
|
def enum_to_bool(enum)
|
@@ -86,9 +87,9 @@ module Aspera
|
|
86
87
|
|
87
88
|
# Generates error message with list of allowed values
|
88
89
|
# @param error_msg [String] error message
|
89
|
-
# @param
|
90
|
-
def multi_choice_assert(assertion, error_msg,
|
91
|
-
raise Cli::BadArgument, [error_msg, 'Use:'].concat(
|
90
|
+
# @param accept_list [Array] list of allowed values
|
91
|
+
def multi_choice_assert(assertion, error_msg, accept_list)
|
92
|
+
raise Cli::BadArgument, [error_msg, 'Use:'].concat(accept_list.map{|c|"- #{c}"}.sort).join("\n") unless assertion
|
92
93
|
end
|
93
94
|
|
94
95
|
# change option name with dash to name with underscore
|
@@ -102,14 +103,17 @@ module Aspera
|
|
102
103
|
|
103
104
|
# @param what [Symbol] :option or :argument
|
104
105
|
# @param descr [String] description for help
|
105
|
-
# @param
|
106
|
+
# @param to_check [Object] value to check
|
106
107
|
# @param type_list [NilClass, Class, Array[Class]] accepted value type(s)
|
107
|
-
def validate_type(what, descr,
|
108
|
+
def validate_type(what, descr, to_check, type_list, check_array: false)
|
108
109
|
return nil if type_list.nil?
|
109
110
|
Aspera.assert(type_list.is_a?(Array) && type_list.all?(Class)){'types must be a Class Array'}
|
110
|
-
|
111
|
-
|
112
|
-
|
111
|
+
value_list = check_array ? to_check : [to_check]
|
112
|
+
value_list.each do |value|
|
113
|
+
raise Cli::BadArgument,
|
114
|
+
"#{what.to_s.capitalize} #{descr} is a #{value.class} but must be #{type_list.length > 1 ? 'one of ' : ''}#{type_list.map(&:name).join(',')}" unless \
|
115
|
+
type_list.any?{|t|value.is_a?(t)}
|
116
|
+
end
|
113
117
|
end
|
114
118
|
end
|
115
119
|
|
@@ -117,7 +121,7 @@ module Aspera
|
|
117
121
|
attr_accessor :ask_missing_mandatory, :ask_missing_optional
|
118
122
|
attr_writer :fail_on_missing_mandatory
|
119
123
|
|
120
|
-
def initialize(program_name)
|
124
|
+
def initialize(program_name, argv = nil)
|
121
125
|
# command line values *not* starting with '-'
|
122
126
|
@unprocessed_cmd_line_arguments = []
|
123
127
|
# command line values starting with '-'
|
@@ -149,14 +153,7 @@ module Aspera
|
|
149
153
|
Log.log.debug{"env=#{@option_pairs_env}".red}
|
150
154
|
@unprocessed_cmd_line_options = []
|
151
155
|
@unprocessed_cmd_line_arguments = []
|
152
|
-
|
153
|
-
|
154
|
-
def parse_command_line(argv)
|
155
|
-
@parser.separator('')
|
156
|
-
@parser.separator('OPTIONS: global')
|
157
|
-
declare(:interactive, 'Use interactive input of missing params', values: :bool, handler: {o: self, m: :ask_missing_mandatory})
|
158
|
-
declare(:ask_options, 'Ask even optional options', values: :bool, handler: {o: self, m: :ask_missing_optional})
|
159
|
-
parse_options!
|
156
|
+
return if argv.nil?
|
160
157
|
process_options = true
|
161
158
|
until argv.empty?
|
162
159
|
value = argv.shift
|
@@ -174,65 +171,63 @@ module Aspera
|
|
174
171
|
end
|
175
172
|
@initial_cli_options = @unprocessed_cmd_line_options.dup.freeze
|
176
173
|
Log.log.debug{"add_cmd_line_options:commands/arguments=#{@unprocessed_cmd_line_arguments},options=#{@unprocessed_cmd_line_options}".red}
|
174
|
+
@parser.separator('')
|
175
|
+
@parser.separator('OPTIONS: global')
|
176
|
+
declare(:interactive, 'Use interactive input of missing params', values: :bool, handler: {o: self, m: :ask_missing_mandatory})
|
177
|
+
declare(:ask_options, 'Ask even optional options', values: :bool, handler: {o: self, m: :ask_missing_optional})
|
178
|
+
declare(:struct_parser, 'Default parser when expected value is a struct', values: %i[json ruby])
|
179
|
+
# do not parse options yet, let's wait for option `-h` to be overriden
|
177
180
|
end
|
178
181
|
|
179
182
|
# @param descr [String] description for help
|
180
|
-
# @param expected is
|
181
|
-
# - Array of allowed value (single value)
|
182
|
-
# - :multiple for remaining values
|
183
|
-
# - :single for a single unconstrained value
|
184
|
-
# - :integer for a single integer value
|
185
183
|
# @param mandatory [Boolean] if true, raise error if option not set
|
186
|
-
# @param
|
184
|
+
# @param multiple [Boolean] if true, return remaining arguments
|
185
|
+
# @param accept_list [Array] list of allowed values (Symbol)
|
186
|
+
# @param validation [Class, Array] accepted value type(s) or list of Symbols
|
187
187
|
# @param aliases [Hash] map of aliases: key = alias, value = real value
|
188
188
|
# @param default [Object] default value
|
189
|
-
# @return value, list or nil
|
190
|
-
def get_next_argument(descr,
|
191
|
-
Aspera.assert(
|
192
|
-
|
193
|
-
|
194
|
-
Aspera.assert(
|
195
|
-
|
196
|
-
allowed_types = type
|
189
|
+
# @return one value, list or nil (if optional and no default)
|
190
|
+
def get_next_argument(descr, mandatory: true, multiple: false, accept_list: nil, validation: String, aliases: nil, default: nil)
|
191
|
+
Aspera.assert(accept_list.nil? || (accept_list.is_a?(Array) && accept_list.all?(Symbol)))
|
192
|
+
validation = Symbol if accept_list
|
193
|
+
Aspera.assert(validation.nil? || validation.is_a?(Class) || (validation.is_a?(Array) && validation.all?(Class))){'validation must be Class or Array of Class'}
|
194
|
+
Aspera.assert(aliases.nil? || (aliases.is_a?(Hash) && aliases.keys.all?(Symbol) && aliases.values.all?(Symbol))){'aliases must be Hash:Symbol: Symbol'}
|
195
|
+
allowed_types = validation
|
197
196
|
unless allowed_types.nil?
|
198
197
|
allowed_types = [allowed_types] unless allowed_types.is_a?(Array)
|
199
198
|
descr = "#{descr} (#{allowed_types.join(', ')})"
|
200
199
|
end
|
201
200
|
result =
|
202
201
|
if !@unprocessed_cmd_line_arguments.empty?
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
if value.length.eql?(1) && value.first.is_a?(Array)
|
211
|
-
value = value.first
|
212
|
-
end
|
213
|
-
value
|
214
|
-
when Array
|
215
|
-
allowed_values = [].concat(expected)
|
202
|
+
how_many = multiple ? @unprocessed_cmd_line_arguments.length : 1
|
203
|
+
values = @unprocessed_cmd_line_arguments.shift(how_many)
|
204
|
+
values = values.map{|v|evaluate_extended_value(v, allowed_types)}
|
205
|
+
# if expecting list and only one arg of type array : it is the list
|
206
|
+
values = values.first if values.length.eql?(1) && values.first.is_a?(Array)
|
207
|
+
if accept_list
|
208
|
+
allowed_values = [].concat(accept_list)
|
216
209
|
allowed_values.concat(aliases.keys) unless aliases.nil?
|
217
|
-
self.class.get_from_list(
|
218
|
-
else Aspera.error_unexpected_value(expected)
|
210
|
+
values = values.map{|v|self.class.get_from_list(v, descr, allowed_values)}
|
219
211
|
end
|
212
|
+
multiple ? values : values.first
|
220
213
|
elsif !default.nil? then default
|
221
214
|
# no value provided, either get value interactively, or exception
|
222
|
-
elsif mandatory then get_interactive(
|
215
|
+
elsif mandatory then get_interactive(descr, multiple: multiple, accept_list: accept_list)
|
223
216
|
end
|
224
|
-
if result.is_a?(String) &&
|
217
|
+
if result.is_a?(String) && validation.eql?(Integer)
|
225
218
|
int_result = Integer(result, exception: false)
|
226
219
|
raise Cli::BadArgument, "Invalid integer: #{result}" if int_result.nil?
|
227
220
|
result = int_result
|
228
221
|
end
|
229
222
|
Log.log.debug{"#{descr}=#{result}"}
|
230
223
|
result = aliases[result] if aliases&.key?(result)
|
231
|
-
|
224
|
+
# if value comes from JSON/YAML, it may come as Integer
|
225
|
+
result = result.to_s if result.is_a?(Integer) && validation.eql?(String)
|
226
|
+
self.class.validate_type(:argument, descr, result, allowed_types, check_array: multiple) unless result.nil? && !mandatory
|
232
227
|
return result
|
233
228
|
end
|
234
229
|
|
235
|
-
def get_next_command(command_list, aliases: nil); return get_next_argument('command',
|
230
|
+
def get_next_command(command_list, aliases: nil); return get_next_argument('command', accept_list: command_list, aliases: aliases); end
|
236
231
|
|
237
232
|
# Get an option value by name
|
238
233
|
# either return value or calls handler, can return nil
|
@@ -261,13 +256,13 @@ module Aspera
|
|
261
256
|
raise Cli::BadArgument, "Missing mandatory option: #{option_symbol}" if mandatory
|
262
257
|
elsif @ask_missing_optional || mandatory
|
263
258
|
# ask_missing_mandatory
|
264
|
-
|
259
|
+
accept_list = nil
|
265
260
|
# print "please enter: #{option_symbol.to_s}"
|
266
261
|
if @declared_options.key?(option_symbol) && attributes.key?(:values)
|
267
|
-
|
262
|
+
accept_list = attributes[:values]
|
268
263
|
end
|
269
|
-
result = get_interactive(
|
270
|
-
set_option(option_symbol, result, 'interactive')
|
264
|
+
result = get_interactive(option_symbol.to_s, option: true, accept_list: accept_list)
|
265
|
+
set_option(option_symbol, result, where: 'interactive')
|
271
266
|
end
|
272
267
|
end
|
273
268
|
self.class.validate_type(:option, option_symbol, result, attributes[:types]) unless result.nil? && !mandatory
|
@@ -275,12 +270,16 @@ module Aspera
|
|
275
270
|
end
|
276
271
|
|
277
272
|
# set an option value by name, either store value or call handler
|
278
|
-
|
273
|
+
# @param option_symbol [Symbol] option name
|
274
|
+
# @param value [String] value to set
|
275
|
+
# @param where [String] where the value comes from
|
276
|
+
# @param expect [Class, Array] expected value type(s)
|
277
|
+
def set_option(option_symbol, value, where: 'code override')
|
279
278
|
Aspera.assert_type(option_symbol, Symbol)
|
280
279
|
raise Cli::BadArgument, "Unknown option: #{option_symbol}" unless @declared_options.key?(option_symbol)
|
281
280
|
attributes = @declared_options[option_symbol]
|
282
281
|
Log.log.warn("#{option_symbol}: Option is deprecated: #{attributes[:deprecation]}") if attributes[:deprecation]
|
283
|
-
value =
|
282
|
+
value = evaluate_extended_value(value, attributes[:types])
|
284
283
|
value = Manager.enum_to_bool(value) if attributes[:values].eql?(BOOLEAN_VALUES)
|
285
284
|
Log.log.debug{"(#{attributes[:read_write]}/#{where}) set #{option_symbol}=#{value}"}
|
286
285
|
self.class.validate_type(:option, option_symbol, value, attributes[:types])
|
@@ -332,18 +331,18 @@ module Aspera
|
|
332
331
|
Log.log.debug{"set attr obj #{option_symbol} (#{handler[:o]},#{handler[:m]})"}
|
333
332
|
opt[:accessor] = AttrAccessor.new(handler[:o], handler[:m], option_symbol)
|
334
333
|
end
|
335
|
-
set_option(option_symbol, default, 'default') unless default.nil?
|
334
|
+
set_option(option_symbol, default, where: 'default') unless default.nil?
|
336
335
|
on_args = [description]
|
337
336
|
case values
|
338
337
|
when nil
|
339
338
|
on_args.push(symbol_to_option(option_symbol, 'VALUE'))
|
340
339
|
on_args.push("-#{short}VALUE") unless short.nil?
|
341
340
|
on_args.push(coerce) unless coerce.nil?
|
342
|
-
@parser.on(*on_args) { |v| set_option(option_symbol, v, SOURCE_USER) }
|
341
|
+
@parser.on(*on_args) { |v| set_option(option_symbol, v, where: SOURCE_USER) }
|
343
342
|
when Array, :bool
|
344
343
|
if values.eql?(:bool)
|
345
344
|
values = BOOLEAN_VALUES
|
346
|
-
set_option(option_symbol, Manager.enum_to_bool(default), 'default') unless default.nil?
|
345
|
+
set_option(option_symbol, Manager.enum_to_bool(default), where: 'default') unless default.nil?
|
347
346
|
end
|
348
347
|
# this option value must be a symbol
|
349
348
|
opt[:values] = values
|
@@ -355,7 +354,7 @@ module Aspera
|
|
355
354
|
on_args[0] = "#{description}: #{help_values}"
|
356
355
|
on_args.push(symbol_to_option(option_symbol, 'ENUM'))
|
357
356
|
on_args.push(values)
|
358
|
-
@parser.on(*on_args){|v|set_option(option_symbol, self.class.get_from_list(v.to_s, description, values), SOURCE_USER)}
|
357
|
+
@parser.on(*on_args){|v|set_option(option_symbol, self.class.get_from_list(v.to_s, description, values), where: SOURCE_USER)}
|
359
358
|
when :date
|
360
359
|
on_args.push(symbol_to_option(option_symbol, 'DATE'))
|
361
360
|
@parser.on(*on_args) do |v|
|
@@ -364,7 +363,7 @@ module Aspera
|
|
364
363
|
when /^-([0-9]+)h/ then Manager.time_to_string(Time.now - (Regexp.last_match(1).to_i * 3600))
|
365
364
|
else v
|
366
365
|
end
|
367
|
-
set_option(option_symbol, time_string, SOURCE_USER)
|
366
|
+
set_option(option_symbol, time_string, where: SOURCE_USER)
|
368
367
|
end
|
369
368
|
when :none
|
370
369
|
Aspera.assert(!block.nil?){"missing block for #{option_symbol}"}
|
@@ -401,6 +400,7 @@ module Aspera
|
|
401
400
|
end
|
402
401
|
|
403
402
|
# get all original options on command line used to generate a config in config file
|
403
|
+
# @return [Hash] options as taken from config file and command line just before command execution
|
404
404
|
def unprocessed_options_with_value
|
405
405
|
result = {}
|
406
406
|
@initial_cli_options.each do |option_value|
|
@@ -457,7 +457,7 @@ module Aspera
|
|
457
457
|
@unprocessed_cmd_line_options = unknown_options
|
458
458
|
end
|
459
459
|
|
460
|
-
def prompt_user_input(prompt, sensitive)
|
460
|
+
def prompt_user_input(prompt, sensitive: false)
|
461
461
|
return $stdin.getpass("#{prompt}> ") if sensitive
|
462
462
|
print("#{prompt}> ")
|
463
463
|
line = $stdin.gets
|
@@ -471,7 +471,7 @@ module Aspera
|
|
471
471
|
# @return [Symbol] selected symbol
|
472
472
|
def prompt_user_input_in_list(prompt, sym_list)
|
473
473
|
loop do
|
474
|
-
input = prompt_user_input(prompt
|
474
|
+
input = prompt_user_input(prompt).to_sym
|
475
475
|
if sym_list.any?{|a|a.eql?(input)}
|
476
476
|
return input
|
477
477
|
else
|
@@ -480,34 +480,49 @@ module Aspera
|
|
480
480
|
end
|
481
481
|
end
|
482
482
|
|
483
|
-
|
483
|
+
# Prompt user for input in a list of symbols
|
484
|
+
# @param descr [String] description for help
|
485
|
+
# @param option [Boolean] true if command line option
|
486
|
+
# @param multiple [Boolean] true if multiple values expected
|
487
|
+
# @param accept_list [Array] list of expected values
|
488
|
+
def get_interactive(descr, option: false, multiple: false, accept_list: nil)
|
489
|
+
what = option ? 'option' : 'argument'
|
484
490
|
if !@ask_missing_mandatory
|
485
|
-
|
486
|
-
|
491
|
+
message = "missing #{what}: #{descr}"
|
492
|
+
if accept_list.nil?
|
493
|
+
raise Cli::BadArgument, message
|
494
|
+
else
|
495
|
+
self.class.multi_choice_assert(false, message, accept_list)
|
496
|
+
end
|
487
497
|
end
|
488
498
|
result = nil
|
489
|
-
sensitive =
|
490
|
-
default_prompt = "#{
|
499
|
+
sensitive = option && @declared_options[descr.to_sym].is_a?(Hash) && @declared_options[descr.to_sym][:sensitive]
|
500
|
+
default_prompt = "#{what}: #{descr}"
|
491
501
|
# ask interactively
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
result
|
503
|
-
else # one fixed
|
504
|
-
result = self.class.get_from_list(prompt_user_input("#{expected.join(' ')}\n#{default_prompt}", sensitive), descr, expected)
|
502
|
+
result = []
|
503
|
+
puts(' (one per line, end with empty line)') if multiple
|
504
|
+
loop do
|
505
|
+
prompt = default_prompt
|
506
|
+
prompt = "#{accept_list.join(' ')}\n#{default_prompt}" if accept_list
|
507
|
+
entry = prompt_user_input(prompt, sensitive: sensitive)
|
508
|
+
break if entry.empty? && multiple
|
509
|
+
entry = ExtendedValue.instance.evaluate(entry)
|
510
|
+
entry = self.class.get_from_list(entry, descr, accept_list) if accept_list
|
511
|
+
return entry unless multiple
|
512
|
+
result.push(entry)
|
505
513
|
end
|
506
514
|
return result
|
507
515
|
end
|
508
516
|
|
509
517
|
private
|
510
518
|
|
519
|
+
def evaluate_extended_value(value, types)
|
520
|
+
if DEFAULT_PARSER_TYPES.include?(types) || (types.is_a?(Array) && types.all?{|t|DEFAULT_PARSER_TYPES.include?(t)})
|
521
|
+
return ExtendedValue.instance.evaluate_with_default(value)
|
522
|
+
end
|
523
|
+
return ExtendedValue.instance.evaluate(value)
|
524
|
+
end
|
525
|
+
|
511
526
|
# generate command line option from option symbol
|
512
527
|
def symbol_to_option(symbol, opt_val = nil)
|
513
528
|
result = [OPTION_PREFIX, symbol.to_s.gsub(OPTION_SEP_SYMBOL, OPTION_SEP_LINE)].join
|
@@ -537,7 +552,7 @@ module Aspera
|
|
537
552
|
end
|
538
553
|
end
|
539
554
|
options_to_set.each do |k, v|
|
540
|
-
set_option(k, v, where)
|
555
|
+
set_option(k, v, where: where)
|
541
556
|
# keep only unprocessed values for next parse
|
542
557
|
unprocessed_options.delete(k)
|
543
558
|
end
|
data/lib/aspera/cli/plugin.rb
CHANGED
@@ -29,7 +29,6 @@ module Aspera
|
|
29
29
|
:value, 'Value for create, update, list filter', types: Hash,
|
30
30
|
deprecation: '(4.14) Use positional value for create/modify or option: query for list/delete')
|
31
31
|
options.declare(:property, 'Name of property to set (modify operation)')
|
32
|
-
options.declare(:id, 'Resource identifier', deprecation: "(4.14) Use positional identifier after verb (#{INSTANCE_OPS.join(',')})")
|
33
32
|
options.declare(:bulk, 'Bulk operation (only some)', values: :bool, default: :no)
|
34
33
|
options.declare(:bfail, 'Bulk operation error handling', values: :bool, default: :yes)
|
35
34
|
end
|
@@ -66,9 +65,7 @@ module Aspera
|
|
66
65
|
# @return [String, Array] identifier or list of ids
|
67
66
|
def instance_identifier(description: 'identifier', as_option: nil, &block)
|
68
67
|
if as_option.nil?
|
69
|
-
|
70
|
-
res_id = options.get_option(:id)
|
71
|
-
res_id = options.get_next_argument(description) if res_id.nil?
|
68
|
+
res_id = options.get_next_argument(description, multiple: options.get_option(:bulk)) if res_id.nil?
|
72
69
|
else
|
73
70
|
res_id = options.get_option(as_option)
|
74
71
|
end
|
@@ -255,7 +252,7 @@ module Aspera
|
|
255
252
|
Log.log.warn("option `value` is deprecated. Use positional parameter for #{command}") unless value.nil?
|
256
253
|
value = options.get_next_argument(
|
257
254
|
"parameters for #{command}#{description.nil? ? '' : " (#{description})"}", mandatory: default.nil?,
|
258
|
-
|
255
|
+
validation: bulk ? Array : type) if value.nil?
|
259
256
|
value = default if value.nil?
|
260
257
|
unless type.nil?
|
261
258
|
type = [type] unless type.is_a?(Array)
|
@@ -4,6 +4,7 @@ require 'aspera/cli/plugins/node'
|
|
4
4
|
require 'aspera/cli/plugins/ats'
|
5
5
|
require 'aspera/cli/basic_auth_plugin'
|
6
6
|
require 'aspera/cli/transfer_agent'
|
7
|
+
require 'aspera/cli/special_values'
|
7
8
|
require 'aspera/agent/node'
|
8
9
|
require 'aspera/transfer/spec'
|
9
10
|
require 'aspera/api/aoc'
|
@@ -123,7 +124,7 @@ module Aspera
|
|
123
124
|
formatter.display_status(pub_key_pem)
|
124
125
|
if !options.get_option(:test_mode)
|
125
126
|
formatter.display_status('Once updated or validated, press enter.')
|
126
|
-
|
127
|
+
Environment.instance.open_uri(instance_url)
|
127
128
|
$stdin.gets
|
128
129
|
end
|
129
130
|
else
|
@@ -137,7 +138,7 @@ module Aspera
|
|
137
138
|
formatter.display_status('- origin: localhost')
|
138
139
|
formatter.display_status('Use the generated client id and secret in the following prompts.'.red)
|
139
140
|
end
|
140
|
-
|
141
|
+
Environment.instance.open_uri("#{instance_url}/admin/api-clients")
|
141
142
|
options.get_option(:client_id, mandatory: true)
|
142
143
|
options.get_option(:client_secret, mandatory: true)
|
143
144
|
use_browser_authentication = true
|
@@ -319,8 +320,8 @@ module Aspera
|
|
319
320
|
# client side is agent
|
320
321
|
# server side is transfer server
|
321
322
|
# in same workspace
|
322
|
-
push_pull = options.get_next_argument('direction',
|
323
|
-
source_folder = options.get_next_argument('folder of source files',
|
323
|
+
push_pull = options.get_next_argument('direction', accept_list: %i[push pull])
|
324
|
+
source_folder = options.get_next_argument('folder of source files', validation: String)
|
324
325
|
case push_pull
|
325
326
|
when :push
|
326
327
|
client_direction = Transfer::Spec::DIRECTION_SEND
|
@@ -415,7 +416,7 @@ module Aspera
|
|
415
416
|
fields = object.keys.reject{|k|k.eql?('certificate')}
|
416
417
|
return { type: :single_object, data: object, fields: fields }
|
417
418
|
when :modify
|
418
|
-
changes = options.get_next_argument('properties',
|
419
|
+
changes = options.get_next_argument('properties', validation: Hash)
|
419
420
|
return do_bulk_operation(command: command, descr: 'identifier', values: res_id) do |one_id|
|
420
421
|
aoc_api.update("#{resource_class_path}/#{one_id}", changes)
|
421
422
|
{'id' => one_id}
|
@@ -427,7 +428,7 @@ module Aspera
|
|
427
428
|
end
|
428
429
|
when :set_pub_key
|
429
430
|
# special : reads private and generate public
|
430
|
-
the_private_key = options.get_next_argument('private_key PEM value',
|
431
|
+
the_private_key = options.get_next_argument('private_key PEM value', validation: String)
|
431
432
|
the_public_key = OpenSSL::PKey::RSA.new(the_private_key).public_key.to_s
|
432
433
|
aoc_api.update(resource_instance_path, {jwt_grant_enabled: true, public_key: the_public_key})
|
433
434
|
return Main.result_success
|
@@ -449,7 +450,7 @@ module Aspera
|
|
449
450
|
case command_admin
|
450
451
|
when :resource
|
451
452
|
Log.log.warn('resource command is deprecated (4.18), directly use the specific command instead')
|
452
|
-
return execute_resource_action(options.get_next_argument('resource',
|
453
|
+
return execute_resource_action(options.get_next_argument('resource', accept_list: ADMIN_OBJECTS))
|
453
454
|
when *ADMIN_OBJECTS
|
454
455
|
return execute_resource_action(command_admin)
|
455
456
|
when :auth_providers
|
@@ -534,7 +535,7 @@ module Aspera
|
|
534
535
|
return {type: :object_list, data: events}
|
535
536
|
when :transfers
|
536
537
|
event_type = command_analytics.to_s
|
537
|
-
filter_resource = options.get_next_argument('resource',
|
538
|
+
filter_resource = options.get_next_argument('resource', accept_list: %i[organizations users nodes])
|
538
539
|
filter_id = options.get_next_argument('identifier', mandatory: false) ||
|
539
540
|
case filter_resource
|
540
541
|
when :organizations then aoc_api.current_user_info['organization_id']
|
@@ -622,7 +623,7 @@ module Aspera
|
|
622
623
|
when :show
|
623
624
|
return { type: :single_object, data: aoc_api.current_user_info(exception: true) }
|
624
625
|
when :modify
|
625
|
-
aoc_api.update("users/#{aoc_api.current_user_info(exception: true)['id']}", options.get_next_argument('properties',
|
626
|
+
aoc_api.update("users/#{aoc_api.current_user_info(exception: true)['id']}", options.get_next_argument('properties', validation: Hash))
|
626
627
|
return Main.result_status('modified')
|
627
628
|
end
|
628
629
|
when :preferences
|
@@ -631,7 +632,7 @@ module Aspera
|
|
631
632
|
when :show
|
632
633
|
return { type: :single_object, data: aoc_api.read(user_preferences_res)[:data] }
|
633
634
|
when :modify
|
634
|
-
aoc_api.update(user_preferences_res, options.get_next_argument('properties',
|
635
|
+
aoc_api.update(user_preferences_res, options.get_next_argument('properties', validation: Hash))
|
635
636
|
return Main.result_status('modified')
|
636
637
|
end
|
637
638
|
end
|
@@ -690,13 +691,13 @@ module Aspera
|
|
690
691
|
].concat(aoc_api.additional_persistence_ids)))
|
691
692
|
end
|
692
693
|
case ids_to_download
|
693
|
-
when
|
694
|
+
when SpecialValues::ALL, SpecialValues::INIT
|
694
695
|
query = query_read_delete(default: PACKAGE_RECEIVED_BASE_QUERY)
|
695
696
|
Aspera.assert_type(query, Hash){'query'}
|
696
697
|
resolve_dropbox_name_default_ws_id(query)
|
697
698
|
# remove from list the ones already downloaded
|
698
699
|
all_ids = api_read_all('packages', query)[:data].map{|e|e['id']}
|
699
|
-
if ids_to_download.eql?(
|
700
|
+
if ids_to_download.eql?(SpecialValues::INIT)
|
700
701
|
Aspera.assert(skip_ids_persistency){'Only with option once_only'}
|
701
702
|
skip_ids_persistency.data.clear.concat(all_ids)
|
702
703
|
skip_ids_persistency.save
|
@@ -758,9 +759,9 @@ module Aspera
|
|
758
759
|
when *NODE4_EXT_COMMANDS
|
759
760
|
return execute_nodegen4_command(command_repo, aoc_api.context[:home_node_id], file_id: aoc_api.context[:home_file_id], scope: Api::Node::SCOPE_USER)
|
760
761
|
when :short_link
|
761
|
-
link_type = options.get_next_argument('link type',
|
762
|
+
link_type = options.get_next_argument('link type', accept_list: %i[public private])
|
762
763
|
short_link_command = options.get_next_command(%i[create delete list])
|
763
|
-
folder_dest = options.get_next_argument('path',
|
764
|
+
folder_dest = options.get_next_argument('path', validation: String)
|
764
765
|
home_node_api = aoc_api.node_api_from(
|
765
766
|
node_id: aoc_api.context[:home_node_id],
|
766
767
|
workspace_id: aoc_api.context[:workspace_id],
|
@@ -3,6 +3,7 @@
|
|
3
3
|
# cspell:ignore initdemo genkey pubkey asperasoft filelists
|
4
4
|
require 'aspera/cli/basic_auth_plugin'
|
5
5
|
require 'aspera/cli/extended_value'
|
6
|
+
require 'aspera/cli/special_values'
|
6
7
|
require 'aspera/cli/version'
|
7
8
|
require 'aspera/cli/formatter'
|
8
9
|
require 'aspera/cli/info'
|
@@ -15,7 +16,7 @@ require 'aspera/transfer/spec'
|
|
15
16
|
require 'aspera/keychain/encrypted_hash'
|
16
17
|
require 'aspera/keychain/macos_security'
|
17
18
|
require 'aspera/proxy_auto_config'
|
18
|
-
require 'aspera/
|
19
|
+
require 'aspera/environment'
|
19
20
|
require 'aspera/persistency_action_once'
|
20
21
|
require 'aspera/id_generator'
|
21
22
|
require 'aspera/persistency_folder'
|
@@ -293,7 +294,7 @@ module Aspera
|
|
293
294
|
Aspera.assert_type(path, String){'Expecting a String for certificate location'}
|
294
295
|
paths_to_add = [path]
|
295
296
|
Log.log.debug{"Adding cert location: #{path}"}
|
296
|
-
if path.eql?(
|
297
|
+
if path.eql?(SpecialValues::DEF)
|
297
298
|
@certificate_store.set_default_paths
|
298
299
|
paths_to_add = [
|
299
300
|
OpenSSL::X509::DEFAULT_CERT_DIR,
|
@@ -324,7 +325,7 @@ module Aspera
|
|
324
325
|
locations = @certificate_paths
|
325
326
|
if locations.nil?
|
326
327
|
# compute default locations
|
327
|
-
self.trusted_cert_locations =
|
328
|
+
self.trusted_cert_locations = SpecialValues::DEF
|
328
329
|
locations = @certificate_paths
|
329
330
|
# restore defaults
|
330
331
|
@certificate_paths = @certificate_store = nil
|
@@ -685,7 +686,7 @@ module Aspera
|
|
685
686
|
api_connect_cdn.call(operation: 'GET', subpath: file_url, save_to_file: File.join(folder_dest, filename))
|
686
687
|
return Main.result_status("Downloaded: #{filename}")
|
687
688
|
when :open
|
688
|
-
|
689
|
+
Environment.instance.open_uri(one_link['href'])
|
689
690
|
return Main.result_status("Opened: #{one_link['href']}")
|
690
691
|
end
|
691
692
|
end
|
@@ -786,11 +787,11 @@ module Aspera
|
|
786
787
|
when :set
|
787
788
|
param_name = options.get_next_argument('parameter name')
|
788
789
|
param_name = Manager.option_line_to_name(param_name)
|
789
|
-
param_value = options.get_next_argument('parameter value')
|
790
|
+
param_value = options.get_next_argument('parameter value', validation: nil)
|
790
791
|
set_preset_key(name, param_name, param_value)
|
791
792
|
return Main.result_nothing
|
792
793
|
when :initialize
|
793
|
-
config_value = options.get_next_argument('extended value',
|
794
|
+
config_value = options.get_next_argument('extended value', validation: Hash)
|
794
795
|
if @config_presets.key?(name)
|
795
796
|
Log.log.warn{"configuration already exists: #{name}, overwriting"}
|
796
797
|
end
|
@@ -804,10 +805,10 @@ module Aspera
|
|
804
805
|
@config_presets[name].merge!(unprocessed_options)
|
805
806
|
return Main.result_status("Updated: #{name}")
|
806
807
|
when :ask
|
807
|
-
options.ask_missing_mandatory =
|
808
|
+
options.ask_missing_mandatory = true
|
808
809
|
@config_presets[name] ||= {}
|
809
|
-
options.get_next_argument('option names',
|
810
|
-
option_value = options.get_interactive(
|
810
|
+
options.get_next_argument('option names', multiple: true).each do |option_name|
|
811
|
+
option_value = options.get_interactive(option_name, option: true)
|
811
812
|
@config_presets[name][option_name] = option_value
|
812
813
|
end
|
813
814
|
return Main.result_status("Updated: #{name}")
|
@@ -879,16 +880,16 @@ module Aspera
|
|
879
880
|
when :preset # newer syntax
|
880
881
|
return execute_preset
|
881
882
|
when :open
|
882
|
-
|
883
|
+
Environment.open_editor(@option_config_file.to_s)
|
883
884
|
return Main.result_nothing
|
884
885
|
when :documentation
|
885
886
|
section = options.get_next_argument('private key file path', mandatory: false)
|
886
887
|
section = "##{section}" unless section.nil?
|
887
|
-
|
888
|
+
Environment.instance.open_uri("#{@help}#{section}")
|
888
889
|
return Main.result_nothing
|
889
890
|
when :genkey # generate new rsa key
|
890
891
|
private_key_path = options.get_next_argument('private key file path')
|
891
|
-
private_key_length = options.get_next_argument('size in bits', mandatory: false,
|
892
|
+
private_key_length = options.get_next_argument('size in bits', mandatory: false, validation: Integer, default: DEFAULT_PRIV_KEY_LENGTH)
|
892
893
|
self.class.generate_rsa_private_key(path: private_key_path, length: private_key_length)
|
893
894
|
return Main.result_status("Generated #{private_key_length} bit RSA key: #{private_key_path}")
|
894
895
|
when :pubkey # get pub key
|
@@ -908,7 +909,7 @@ module Aspera
|
|
908
909
|
return Main.result_status(remote_chain.first.subject.to_a.find { |name, _, _| name == 'CN' }[1])
|
909
910
|
end
|
910
911
|
when :echo # display the content of a value given on command line
|
911
|
-
return Formatter.auto_type(options.get_next_argument('value'))
|
912
|
+
return Formatter.auto_type(options.get_next_argument('value', validation: nil))
|
912
913
|
when :flush_tokens
|
913
914
|
deleted_files = OAuth::Factory.instance.flush_tokens
|
914
915
|
return {type: :value_list, data: deleted_files, name: 'file'}
|
@@ -927,8 +928,8 @@ module Aspera
|
|
927
928
|
end
|
928
929
|
return {type: :object_list, data: result, fields: %w[plugin detect wizard path]}
|
929
930
|
when :create
|
930
|
-
plugin_name = options.get_next_argument('name'
|
931
|
-
destination_folder = options.get_next_argument('folder',
|
931
|
+
plugin_name = options.get_next_argument('name').downcase
|
932
|
+
destination_folder = options.get_next_argument('folder', mandatory: false) || File.join(@main_folder, ASPERA_PLUGINS_FOLDERNAME)
|
932
933
|
plugin_file = File.join(destination_folder, "#{plugin_name}.rb")
|
933
934
|
content = <<~END_OF_PLUGIN_CODE
|
934
935
|
require 'aspera/cli/plugin'
|
@@ -1077,7 +1078,7 @@ module Aspera
|
|
1077
1078
|
Log.log.debug{"wizard result: #{wizard_result}"}
|
1078
1079
|
Aspera.assert(WIZARD_RESULT_KEYS.eql?(wizard_result.keys.sort)){"missing or extra keys in wizard result: #{wizard_result.keys}"}
|
1079
1080
|
# get preset name from user or default
|
1080
|
-
wiz_preset_name =
|
1081
|
+
wiz_preset_name = nil
|
1081
1082
|
if wiz_preset_name.nil?
|
1082
1083
|
elements = [
|
1083
1084
|
identification[:product],
|
@@ -1217,8 +1218,8 @@ module Aspera
|
|
1217
1218
|
when :show
|
1218
1219
|
return {type: :single_object, data: vault.get(label: options.get_next_argument('label'))}
|
1219
1220
|
when :create
|
1220
|
-
label = options.get_next_argument('label',
|
1221
|
-
info = options.get_next_argument('info',
|
1221
|
+
label = options.get_next_argument('label', validation: String)
|
1222
|
+
info = options.get_next_argument('info', validation: Hash)
|
1222
1223
|
info = info.symbolize_keys
|
1223
1224
|
info[:label] = label
|
1224
1225
|
vault.set(info)
|
@@ -1270,7 +1271,7 @@ module Aspera
|
|
1270
1271
|
info[:password])
|
1271
1272
|
when 'system'
|
1272
1273
|
case Environment.os
|
1273
|
-
when Environment::
|
1274
|
+
when Environment::OS_MACOS
|
1274
1275
|
@vault = Keychain::MacosSystem.new(info[:name], info[:password])
|
1275
1276
|
else
|
1276
1277
|
raise 'not implemented for this OS'
|