aspera-cli 4.20.0 → 4.21.2
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/CHANGELOG.md +41 -3
- data/CONTRIBUTING.md +69 -142
- data/README.md +687 -461
- data/bin/ascli +5 -14
- data/bin/asession +3 -5
- data/examples/get_proto_file.rb +4 -3
- data/examples/proxy.pac +20 -20
- data/lib/aspera/agent/base.rb +2 -0
- data/lib/aspera/agent/connect.rb +20 -2
- data/lib/aspera/agent/{alpha.rb → desktop.rb} +12 -18
- data/lib/aspera/agent/direct.rb +30 -31
- data/lib/aspera/agent/node.rb +1 -11
- data/lib/aspera/agent/{trsdk.rb → transferd.rb} +37 -51
- data/lib/aspera/api/alee.rb +1 -1
- data/lib/aspera/api/aoc.rb +13 -8
- data/lib/aspera/api/cos_node.rb +1 -1
- data/lib/aspera/api/node.rb +49 -32
- data/lib/aspera/ascp/installation.rb +98 -77
- data/lib/aspera/ascp/management.rb +27 -6
- data/lib/aspera/cli/extended_value.rb +9 -3
- data/lib/aspera/cli/formatter.rb +155 -154
- data/lib/aspera/cli/info.rb +2 -1
- data/lib/aspera/cli/main.rb +12 -0
- data/lib/aspera/cli/manager.rb +4 -4
- data/lib/aspera/cli/plugin.rb +2 -2
- data/lib/aspera/cli/plugins/aoc.rb +134 -73
- data/lib/aspera/cli/plugins/config.rb +114 -83
- data/lib/aspera/cli/plugins/cos.rb +1 -0
- data/lib/aspera/cli/plugins/faspex.rb +4 -2
- data/lib/aspera/cli/plugins/faspex5.rb +29 -14
- data/lib/aspera/cli/plugins/node.rb +51 -41
- data/lib/aspera/cli/transfer_progress.rb +2 -0
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/command_line_builder.rb +1 -1
- data/lib/aspera/coverage.rb +5 -3
- data/lib/aspera/environment.rb +59 -16
- data/lib/aspera/faspex_postproc.rb +3 -5
- data/lib/aspera/hash_ext.rb +2 -12
- data/lib/aspera/node_simulator.rb +230 -112
- data/lib/aspera/oauth/base.rb +40 -48
- data/lib/aspera/oauth/factory.rb +41 -2
- data/lib/aspera/oauth/jwt.rb +4 -1
- data/lib/aspera/persistency_action_once.rb +1 -1
- data/lib/aspera/persistency_folder.rb +20 -2
- data/lib/aspera/preview/generator.rb +13 -10
- data/lib/aspera/preview/options.rb +2 -2
- data/lib/aspera/preview/terminal.rb +1 -1
- data/lib/aspera/preview/utils.rb +11 -6
- data/lib/aspera/products/connect.rb +82 -0
- data/lib/aspera/products/desktop.rb +30 -0
- data/lib/aspera/products/other.rb +82 -0
- data/lib/aspera/products/transferd.rb +61 -0
- data/lib/aspera/rest.rb +22 -17
- data/lib/aspera/secret_hider.rb +9 -2
- data/lib/aspera/ssh.rb +31 -24
- data/lib/aspera/temp_file_manager.rb +5 -4
- data/lib/aspera/transfer/parameters.rb +2 -1
- data/lib/aspera/transfer/spec.yaml +22 -20
- data/lib/aspera/transfer/sync.rb +1 -5
- data/lib/aspera/transfer/uri.rb +2 -2
- data/lib/aspera/uri_reader.rb +18 -1
- data/lib/transferd_pb.rb +86 -0
- data/lib/transferd_services_pb.rb +84 -0
- data.tar.gz.sig +0 -0
- metadata +13 -166
- metadata.gz.sig +0 -0
- data/examples/build_exec +0 -74
- data/examples/build_exec_rubyc +0 -40
- data/lib/aspera/ascp/products.rb +0 -168
- data/lib/transfer_pb.rb +0 -84
- data/lib/transfer_services_pb.rb +0 -82
@@ -21,6 +21,13 @@ module Aspera
|
|
21
21
|
MARKER_END = ':'
|
22
22
|
MARKER_IN_END = '@'
|
23
23
|
|
24
|
+
# special handlers stop processing of handlers on right
|
25
|
+
# extend includes processing of other handlers in itself
|
26
|
+
# val keeps the value intact
|
27
|
+
SPECIAL_HANDLERS = %i[extend val].freeze
|
28
|
+
|
29
|
+
private_constant :MARKER_START, :MARKER_END, :MARKER_IN_END, :SPECIAL_HANDLERS
|
30
|
+
|
24
31
|
class << self
|
25
32
|
# decode comma separated table text
|
26
33
|
def decode_csvt(value)
|
@@ -64,7 +71,7 @@ module Aspera
|
|
64
71
|
ruby: lambda{|v|Environment.secure_eval(v, __FILE__, __LINE__)},
|
65
72
|
secret: lambda{|v|prompt = v.empty? ? 'secret' : v; $stdin.getpass("#{prompt}> ")}, # rubocop:disable Style/Semicolon
|
66
73
|
stdin: lambda{|v|ExtendedValue.assert_no_value(v, :stdin); $stdin.read}, # rubocop:disable Style/Semicolon
|
67
|
-
stdbin: lambda{|v|ExtendedValue.assert_no_value(v, :
|
74
|
+
stdbin: lambda{|v|ExtendedValue.assert_no_value(v, :stdbin); $stdin.binmode.read}, # rubocop:disable Style/Semicolon
|
68
75
|
yaml: lambda{|v|YAML.load(v)},
|
69
76
|
zlib: lambda{|v|Zlib::Inflate.inflate(v)},
|
70
77
|
extend: lambda{|v|ExtendedValue.instance.evaluate_all(v)}
|
@@ -107,8 +114,7 @@ module Aspera
|
|
107
114
|
handler = m[1].to_sym
|
108
115
|
handlers_reversed.unshift(handler)
|
109
116
|
value = m[2]
|
110
|
-
|
111
|
-
break if handler.eql?(:extend)
|
117
|
+
break if SPECIAL_HANDLERS.include?(handler)
|
112
118
|
end
|
113
119
|
Log.log.trace1{"evaluating: #{handlers_reversed}, value: #{value}"}
|
114
120
|
handlers_reversed.each do |handler|
|
data/lib/aspera/cli/formatter.rb
CHANGED
@@ -14,7 +14,6 @@ require 'pp'
|
|
14
14
|
|
15
15
|
module Aspera
|
16
16
|
module Cli
|
17
|
-
CONF_OVERVIEW_KEYS = %w[preset parameter value].freeze
|
18
17
|
# This class is used to transform a complex structure into a simple hash
|
19
18
|
class Flattener
|
20
19
|
def initialize(formatter)
|
@@ -30,17 +29,6 @@ module Aspera
|
|
30
29
|
return @result
|
31
30
|
end
|
32
31
|
|
33
|
-
# Special method for configuration overview
|
34
|
-
def config_over(something)
|
35
|
-
@result = []
|
36
|
-
something.each do |config, preset|
|
37
|
-
preset.each do |parameter, value|
|
38
|
-
@result.push(CONF_OVERVIEW_KEYS.zip([config, parameter, value]).to_h)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
return @result
|
42
|
-
end
|
43
|
-
|
44
32
|
private
|
45
33
|
|
46
34
|
# Recursive function to flatten any type
|
@@ -101,9 +89,10 @@ module Aspera
|
|
101
89
|
DISPLAY_FORMATS = %i[text nagios ruby json jsonpp yaml table csv image].freeze
|
102
90
|
# user output levels
|
103
91
|
DISPLAY_LEVELS = %i[info data error].freeze
|
104
|
-
|
92
|
+
# column names for single object display in table
|
93
|
+
SINGLE_OBJECT_COLUMN_NAMES = %i[field value].freeze
|
105
94
|
|
106
|
-
private_constant :
|
95
|
+
private_constant :FIELDS_LESS, :CSV_RECORD_SEPARATOR, :CSV_FIELD_SEPARATOR, :DISPLAY_FORMATS, :DISPLAY_LEVELS, :SINGLE_OBJECT_COLUMN_NAMES
|
107
96
|
# prefix to display error messages in user messages (terminal)
|
108
97
|
ERROR_FLASH = 'ERROR:'.bg_red.gray.blink.freeze
|
109
98
|
WARNING_FLASH = 'WARNING:'.bg_brown.black.blink.freeze
|
@@ -172,12 +161,37 @@ module Aspera
|
|
172
161
|
@spinner = nil
|
173
162
|
end
|
174
163
|
|
175
|
-
|
164
|
+
def declare_options(options)
|
165
|
+
default_table_style = if Environment.instance.terminal_supports_unicode?
|
166
|
+
{border: :unicode_round}
|
167
|
+
else
|
168
|
+
{}
|
169
|
+
end
|
170
|
+
options.declare(:format, 'Output format', values: DISPLAY_FORMATS, handler: {o: self, m: :option_handler}, default: :table)
|
171
|
+
options.declare(:output, 'Destination for results', types: String, handler: {o: self, m: :option_handler})
|
172
|
+
options.declare(:display, 'Output only some information', values: DISPLAY_LEVELS, handler: {o: self, m: :option_handler}, default: :info)
|
173
|
+
options.declare(
|
174
|
+
:fields, "Comma separated list of: fields, or #{SpecialValues::ALL}, or #{SpecialValues::DEF}", handler: {o: self, m: :option_handler},
|
175
|
+
types: [String, Array, Regexp, Proc],
|
176
|
+
default: SpecialValues::DEF)
|
177
|
+
options.declare(:select, 'Select only some items in lists: column, value', types: [Hash, Proc], handler: {o: self, m: :option_handler})
|
178
|
+
options.declare(:table_style, 'Table display style', types: [Hash], handler: {o: self, m: :option_handler}, default: default_table_style)
|
179
|
+
options.declare(:flat_hash, '(Table) Display deep values as additional keys', values: :bool, handler: {o: self, m: :option_handler}, default: true)
|
180
|
+
options.declare(
|
181
|
+
:multi_single, '(Table) Control how object list is displayed as single table, or multiple objects', values: %i[no yes single],
|
182
|
+
handler: {o: self, m: :option_handler}, default: :no)
|
183
|
+
options.declare(:show_secrets, 'Show secrets on command output', values: :bool, handler: {o: self, m: :option_handler}, default: false)
|
184
|
+
options.declare(:image, 'Options for image display', types: Hash, handler: {o: self, m: :option_handler}, default: {})
|
185
|
+
end
|
186
|
+
|
187
|
+
# method accessed by option manager
|
188
|
+
# options are: format, output, display, fields, select, table_style, flat_hash, multi_single
|
176
189
|
def option_handler(option_symbol, operation, value=nil)
|
177
190
|
Aspera.assert_values(operation, %i[set get])
|
178
191
|
case operation
|
179
192
|
when :set
|
180
193
|
@options[option_symbol] = value
|
194
|
+
# special handling of some options
|
181
195
|
case option_symbol
|
182
196
|
when :output
|
183
197
|
$stdout = if value.eql?('-')
|
@@ -186,7 +200,9 @@ module Aspera
|
|
186
200
|
File.open(value, 'w')
|
187
201
|
end
|
188
202
|
when :image
|
203
|
+
# get list if key arguments of method
|
189
204
|
allowed_options = Preview::Terminal.method(:build).parameters.select{|i|i[0].eql?(:key)}.map{|i|i[1]}
|
205
|
+
# check that only supported options are given
|
190
206
|
unknown_options = value.keys.map(&:to_sym) - allowed_options
|
191
207
|
raise "Invalid parameter(s) for option image: #{unknown_options.join(', ')}, use #{allowed_options.join(', ')}" unless unknown_options.empty?
|
192
208
|
end
|
@@ -196,33 +212,12 @@ module Aspera
|
|
196
212
|
nil
|
197
213
|
end
|
198
214
|
|
199
|
-
def declare_options(options)
|
200
|
-
default_table_style = if Environment.instance.terminal_supports_unicode?
|
201
|
-
{border: :unicode_round}
|
202
|
-
else
|
203
|
-
{}
|
204
|
-
end
|
205
|
-
options.declare(:format, 'Output format', values: DISPLAY_FORMATS, handler: {o: self, m: :option_handler}, default: :table)
|
206
|
-
options.declare(:output, 'Destination for results', types: String, handler: {o: self, m: :option_handler})
|
207
|
-
options.declare(:display, 'Output only some information', values: DISPLAY_LEVELS, handler: {o: self, m: :option_handler}, default: :info)
|
208
|
-
options.declare(
|
209
|
-
:fields, "Comma separated list of: fields, or #{SpecialValues::ALL}, or #{SpecialValues::DEF}", handler: {o: self, m: :option_handler},
|
210
|
-
types: [String, Array, Regexp, Proc],
|
211
|
-
default: SpecialValues::DEF)
|
212
|
-
options.declare(:select, 'Select only some items in lists: column, value', types: [Hash, Proc], handler: {o: self, m: :option_handler})
|
213
|
-
options.declare(:table_style, 'Table display style', types: [Hash], handler: {o: self, m: :option_handler}, default: default_table_style)
|
214
|
-
options.declare(:flat_hash, '(Table) Display deep values as additional keys', values: :bool, handler: {o: self, m: :option_handler}, default: true)
|
215
|
-
options.declare(:transpose_single, '(Table) Single object fields output vertically', values: :bool, handler: {o: self, m: :option_handler}, default: true)
|
216
|
-
options.declare(:multi_table, '(Table) Each element of a table are displayed as a table', values: :bool, handler: {o: self, m: :option_handler}, default: false)
|
217
|
-
options.declare(:show_secrets, 'Show secrets on command output', values: :bool, handler: {o: self, m: :option_handler}, default: false)
|
218
|
-
options.declare(:image, 'Options for image display', types: Hash, handler: {o: self, m: :option_handler}, default: {})
|
219
|
-
end
|
220
|
-
|
221
215
|
# main output method
|
222
216
|
# data: for requested data, not displayed if level==error
|
223
217
|
# info: additional info, displayed if level==info
|
224
218
|
# error: always displayed on stderr
|
225
219
|
def display_message(message_level, message)
|
220
|
+
message = SecretHider.hide_secrets_in_string(message) if message.is_a?(String) && hide_secrets?
|
226
221
|
case message_level
|
227
222
|
when :data then $stdout.puts(message) unless @options[:display].eql?(:error)
|
228
223
|
when :info then $stdout.puts(message) if @options[:display].eql?(:info)
|
@@ -244,6 +239,122 @@ module Aspera
|
|
244
239
|
display_status(count_msg)
|
245
240
|
end
|
246
241
|
|
242
|
+
def hide_secrets?
|
243
|
+
!@options[:show_secrets] && !@options[:display].eql?(:data)
|
244
|
+
end
|
245
|
+
|
246
|
+
# hides secrets in Hash or Array
|
247
|
+
def hide_secrets(data)
|
248
|
+
SecretHider.deep_remove_secret(data) if hide_secrets?
|
249
|
+
end
|
250
|
+
|
251
|
+
# this method displays the results, especially the table format
|
252
|
+
# @param type [Symbol] type of data
|
253
|
+
# @param data [Object] data to display
|
254
|
+
# @param total [Integer] total number of items
|
255
|
+
# @param fields [Array<String>] list of fields to display
|
256
|
+
# @param name [String] name of the column to display
|
257
|
+
def display_results(type:, data: nil, total: nil, fields: nil, name: nil)
|
258
|
+
Log.log.debug{"display_results: #{type} class=#{data.class}"}
|
259
|
+
Log.log.trace1{"display_results:data=#{data}"}
|
260
|
+
Aspera.assert_type(type, Symbol){'result must have type'}
|
261
|
+
Aspera.assert(!data.nil? || %i[empty nothing].include?(type)){'result must have data'}
|
262
|
+
display_item_count(data.length, total) unless total.nil?
|
263
|
+
hide_secrets(data)
|
264
|
+
data = SecretHider.hide_secrets_in_string(data) if data.is_a?(String) && hide_secrets?
|
265
|
+
case @options[:format]
|
266
|
+
when :text
|
267
|
+
display_message(:data, data.to_s)
|
268
|
+
when :nagios
|
269
|
+
Nagios.process(data)
|
270
|
+
when :ruby
|
271
|
+
display_message(:data, PP.pp(filter_list_on_fields(data), +''))
|
272
|
+
when :json
|
273
|
+
display_message(:data, JSON.generate(filter_list_on_fields(data)))
|
274
|
+
when :jsonpp
|
275
|
+
display_message(:data, JSON.pretty_generate(filter_list_on_fields(data)))
|
276
|
+
when :yaml
|
277
|
+
display_message(:data, YAML.dump(filter_list_on_fields(data)))
|
278
|
+
when :image
|
279
|
+
# assume it is an url
|
280
|
+
url = data
|
281
|
+
case type
|
282
|
+
when :single_object, :object_list
|
283
|
+
url = [url] if type.eql?(:single_object)
|
284
|
+
raise 'image display requires a single result' unless url.length == 1
|
285
|
+
fields = compute_fields(url, fields)
|
286
|
+
raise 'select a field to display' unless fields.length == 1
|
287
|
+
url = url.first
|
288
|
+
raise 'no such field' unless url.key?(fields.first)
|
289
|
+
url = url[fields.first]
|
290
|
+
end
|
291
|
+
raise "not url: #{url.class} #{url}" unless url.is_a?(String)
|
292
|
+
display_message(:data, status_image(url))
|
293
|
+
when :table, :csv
|
294
|
+
case type
|
295
|
+
when :object_list, :single_object
|
296
|
+
obj_list = data
|
297
|
+
if type.eql?(:single_object)
|
298
|
+
obj_list = [obj_list]
|
299
|
+
@options[:multi_single] = :yes
|
300
|
+
end
|
301
|
+
Aspera.assert_type(obj_list, Array)
|
302
|
+
Aspera.assert(obj_list.all?(Hash)){"expecting Array of Hash: #{obj_list.inspect}"}
|
303
|
+
# :object_list is an array of hash tables, where key=colum name
|
304
|
+
obj_list = obj_list.map{|obj|Flattener.new(self).flatten(obj)} if @options[:flat_hash]
|
305
|
+
display_table(obj_list, compute_fields(obj_list, fields))
|
306
|
+
when :value_list
|
307
|
+
# :value_list is a simple array of values, name of column provided in the :name
|
308
|
+
display_table(data.map { |i| { name => i } }, [name])
|
309
|
+
when :empty # no table
|
310
|
+
display_message(:info, special_format('empty'))
|
311
|
+
return
|
312
|
+
when :nothing # no result expected
|
313
|
+
Log.log.debug('no result expected')
|
314
|
+
when :status # no table
|
315
|
+
# :status displays a simple message
|
316
|
+
display_message(:info, data)
|
317
|
+
when :text # no table
|
318
|
+
# :status displays a simple message
|
319
|
+
display_message(:data, data)
|
320
|
+
when :other_struct # no table
|
321
|
+
# :other_struct is any other type of structure
|
322
|
+
display_message(:data, PP.pp(data, +''))
|
323
|
+
else
|
324
|
+
raise "unknown data type: #{type}"
|
325
|
+
end
|
326
|
+
else
|
327
|
+
raise "not expected: #{@options[:format]}"
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
# @return text suitable to display an image from url
|
332
|
+
# @param blob [String] either a URL or image data
|
333
|
+
def status_image(blob)
|
334
|
+
# check if URL
|
335
|
+
begin
|
336
|
+
URI.parse(blob)
|
337
|
+
url = blob
|
338
|
+
unless Environment.instance.url_method.eql?(:text)
|
339
|
+
Environment.instance.open_uri(url)
|
340
|
+
return ''
|
341
|
+
end
|
342
|
+
blob = UriReader.read(url)
|
343
|
+
rescue URI::InvalidURIError
|
344
|
+
nil
|
345
|
+
end
|
346
|
+
# try base64
|
347
|
+
begin
|
348
|
+
blob = Base64.strict_decode64(blob)
|
349
|
+
rescue
|
350
|
+
nil
|
351
|
+
end
|
352
|
+
return Preview::Terminal.build(blob, **@options[:image].symbolize_keys)
|
353
|
+
end
|
354
|
+
#==========================================================================================
|
355
|
+
|
356
|
+
private
|
357
|
+
|
247
358
|
def all_fields(data)
|
248
359
|
data.each_with_object({}){|v, m|v.each_key{|c|m[c] = true}}.keys
|
249
360
|
end
|
@@ -300,7 +411,7 @@ module Aspera
|
|
300
411
|
return data if @options[:fields].eql?(SpecialValues::DEF)
|
301
412
|
selected_fields = compute_fields(data, @options[:fields])
|
302
413
|
return data.map{|i|i[selected_fields.first]} if selected_fields.length == 1
|
303
|
-
return data.map{|i|i.
|
414
|
+
return data.map{|i|i.slice(*selected_fields)}
|
304
415
|
end
|
305
416
|
|
306
417
|
# filter the list of items on the select option
|
@@ -314,9 +425,9 @@ module Aspera
|
|
314
425
|
end
|
315
426
|
end
|
316
427
|
|
317
|
-
#
|
318
|
-
# object_array
|
319
|
-
# fields
|
428
|
+
# displays a list of objects
|
429
|
+
# @param object_array [Array] array of hash
|
430
|
+
# @param fields [Array] list of column names
|
320
431
|
def display_table(object_array, fields)
|
321
432
|
Aspera.assert(!fields.nil?){'missing fields parameter'}
|
322
433
|
filter_columns_on_select(object_array)
|
@@ -330,13 +441,6 @@ module Aspera
|
|
330
441
|
display_message(:data, object_array.first[fields.first])
|
331
442
|
return
|
332
443
|
end
|
333
|
-
single_transposed = @options[:transpose_single] && object_array.length == 1
|
334
|
-
# Special case if only one row (it could be object_list or single_object)
|
335
|
-
if single_transposed
|
336
|
-
single = object_array.first
|
337
|
-
object_array = fields.map { |i| FIELD_VALUE_HEADINGS.zip([i, single[i]]).to_h }
|
338
|
-
fields = FIELD_VALUE_HEADINGS
|
339
|
-
end
|
340
444
|
Log.log.debug{Log.dump(:object_array, object_array)}
|
341
445
|
# convert data to string, and keep only display fields
|
342
446
|
final_table_rows = object_array.map { |r| fields.map { |c| r[c].to_s } }
|
@@ -345,11 +449,12 @@ module Aspera
|
|
345
449
|
# here : fields : list of column names
|
346
450
|
case @options[:format]
|
347
451
|
when :table
|
348
|
-
if @options[:
|
452
|
+
if @options[:multi_single].eql?(:yes) ||
|
453
|
+
(@options[:multi_single].eql?(:single) && final_table_rows.length.eql?(1))
|
349
454
|
final_table_rows.each do |row|
|
350
455
|
Log.log.debug{Log.dump(:row, row)}
|
351
456
|
display_message(:data, Terminal::Table.new(
|
352
|
-
headings:
|
457
|
+
headings: SINGLE_OBJECT_COLUMN_NAMES,
|
353
458
|
rows: fields.zip(row),
|
354
459
|
style: @options[:table_style]&.symbolize_keys))
|
355
460
|
end
|
@@ -366,110 +471,6 @@ module Aspera
|
|
366
471
|
raise "not expected: #{@options[:format]}"
|
367
472
|
end
|
368
473
|
end
|
369
|
-
|
370
|
-
# @return text suitable to display an image from url
|
371
|
-
def status_image(blob)
|
372
|
-
begin
|
373
|
-
raise URI::InvalidURIError, 'not uri' if !(blob =~ /\A#{URI::RFC2396_PARSER.make_regexp}\z/)
|
374
|
-
# it's a url
|
375
|
-
url = blob
|
376
|
-
unless Environment.instance.url_method.eql?(:text)
|
377
|
-
Environment.instance.open_uri(url)
|
378
|
-
return ''
|
379
|
-
end
|
380
|
-
# remote_image = Rest.new(base_url: url).read('')
|
381
|
-
# mime = remote_image[:http]['content-type']
|
382
|
-
# blob = remote_image[:http].body
|
383
|
-
# Log.log.warn("Image ? #{remote_image[:http]['content-type']}") unless mime.include?('image/')
|
384
|
-
blob = UriReader.read(url)
|
385
|
-
rescue URI::InvalidURIError
|
386
|
-
nil
|
387
|
-
end
|
388
|
-
# try base64
|
389
|
-
begin
|
390
|
-
blob = Base64.strict_decode64(blob)
|
391
|
-
rescue
|
392
|
-
nil
|
393
|
-
end
|
394
|
-
return Preview::Terminal.build(blob, **@options[:image].symbolize_keys)
|
395
|
-
end
|
396
|
-
|
397
|
-
# this method displays the results, especially the table format
|
398
|
-
# @param type [Symbol] type of data
|
399
|
-
# @param data [Object] data to display
|
400
|
-
# @param total [Integer] total number of items
|
401
|
-
# @param fields [Array<String>] list of fields to display
|
402
|
-
# @param name [String] name of the column to display
|
403
|
-
def display_results(type:, data: nil, total: nil, fields: nil, name: nil)
|
404
|
-
Log.log.debug{"display_results: #{type} class=#{data.class} data=#{data}"}
|
405
|
-
Aspera.assert_type(type, Symbol){'result must have type'}
|
406
|
-
Aspera.assert(!data.nil? || %i[empty nothing].include?(type)){'result must have data'}
|
407
|
-
display_item_count(data.length, total) unless total.nil?
|
408
|
-
SecretHider.deep_remove_secret(data) unless @options[:show_secrets] || @options[:display].eql?(:data)
|
409
|
-
case @options[:format]
|
410
|
-
when :text
|
411
|
-
display_message(:data, data.to_s)
|
412
|
-
when :nagios
|
413
|
-
Nagios.process(data)
|
414
|
-
when :ruby
|
415
|
-
display_message(:data, PP.pp(filter_list_on_fields(data), +''))
|
416
|
-
when :json
|
417
|
-
display_message(:data, JSON.generate(filter_list_on_fields(data)))
|
418
|
-
when :jsonpp
|
419
|
-
display_message(:data, JSON.pretty_generate(filter_list_on_fields(data)))
|
420
|
-
when :yaml
|
421
|
-
display_message(:data, YAML.dump(filter_list_on_fields(data)))
|
422
|
-
when :image
|
423
|
-
# assume it is an url
|
424
|
-
url = data
|
425
|
-
case type
|
426
|
-
when :single_object, :object_list
|
427
|
-
url = [url] if type.eql?(:single_object)
|
428
|
-
raise 'image display requires a single result' unless url.length == 1
|
429
|
-
fields = compute_fields(url, fields)
|
430
|
-
raise 'select a field to display' unless fields.length == 1
|
431
|
-
url = url.first
|
432
|
-
raise 'no such field' unless url.key?(fields.first)
|
433
|
-
url = url[fields.first]
|
434
|
-
end
|
435
|
-
raise "not url: #{url.class} #{url}" unless url.is_a?(String)
|
436
|
-
display_message(:data, status_image(url))
|
437
|
-
when :table, :csv
|
438
|
-
case type
|
439
|
-
when :config_over
|
440
|
-
display_table(Flattener.new(self).config_over(data), CONF_OVERVIEW_KEYS)
|
441
|
-
when :object_list, :single_object
|
442
|
-
obj_list = data
|
443
|
-
obj_list = [obj_list] if type.eql?(:single_object)
|
444
|
-
Aspera.assert_type(obj_list, Array)
|
445
|
-
Aspera.assert(obj_list.all?(Hash)){"expecting Array of Hash: #{obj_list.inspect}"}
|
446
|
-
# :object_list is an array of hash tables, where key=colum name
|
447
|
-
obj_list = obj_list.map{|obj|Flattener.new(self).flatten(obj)} if @options[:flat_hash]
|
448
|
-
display_table(obj_list, compute_fields(obj_list, fields))
|
449
|
-
when :value_list
|
450
|
-
# :value_list is a simple array of values, name of column provided in the :name
|
451
|
-
display_table(data.map { |i| { name => i } }, [name])
|
452
|
-
when :empty # no table
|
453
|
-
display_message(:info, special_format('empty'))
|
454
|
-
return
|
455
|
-
when :nothing # no result expected
|
456
|
-
Log.log.debug('no result expected')
|
457
|
-
when :status # no table
|
458
|
-
# :status displays a simple message
|
459
|
-
display_message(:info, data)
|
460
|
-
when :text # no table
|
461
|
-
# :status displays a simple message
|
462
|
-
display_message(:data, data)
|
463
|
-
when :other_struct # no table
|
464
|
-
# :other_struct is any other type of structure
|
465
|
-
display_message(:data, PP.pp(data, +''))
|
466
|
-
else
|
467
|
-
raise "unknown data type: #{type}"
|
468
|
-
end
|
469
|
-
else
|
470
|
-
raise "not expected: #{@options[:format]}"
|
471
|
-
end
|
472
|
-
end
|
473
474
|
end
|
474
475
|
end
|
475
476
|
end
|
data/lib/aspera/cli/info.rb
CHANGED
@@ -10,9 +10,10 @@ module Aspera
|
|
10
10
|
DOC_URL = "https://www.rubydoc.info/gems/#{GEM_NAME}"
|
11
11
|
GEM_URL = "https://rubygems.org/gems/#{GEM_NAME}"
|
12
12
|
SRC_URL = 'https://github.com/IBM/aspera-cli'
|
13
|
+
CONTAINER = 'docker.io/martinlaurent/ascli'
|
13
14
|
# set this to warn in advance when minimum required ruby version will increase
|
14
15
|
# see also required_ruby_version in gemspec file
|
15
|
-
RUBY_FUTURE_MINIMUM_VERSION = '3.
|
16
|
+
RUBY_FUTURE_MINIMUM_VERSION = '3.2'
|
16
17
|
end
|
17
18
|
end
|
18
19
|
end
|
data/lib/aspera/cli/main.rb
CHANGED
@@ -63,6 +63,18 @@ module Aspera
|
|
63
63
|
def result_image(blob, formatter:)
|
64
64
|
return Main.result_status(formatter.status_image(blob))
|
65
65
|
end
|
66
|
+
|
67
|
+
def result_single_object(data, fields: nil)
|
68
|
+
return {type: :single_object, data: data, fields: fields}
|
69
|
+
end
|
70
|
+
|
71
|
+
def result_object_list(data, fields: nil, total: nil)
|
72
|
+
return {type: :object_list, data: data, fields: fields, total: nil}
|
73
|
+
end
|
74
|
+
|
75
|
+
def result_value_list(data, name)
|
76
|
+
return {type: :value_list, data: data, name: name}
|
77
|
+
end
|
66
78
|
end
|
67
79
|
|
68
80
|
private
|
data/lib/aspera/cli/manager.rb
CHANGED
@@ -105,13 +105,14 @@ module Aspera
|
|
105
105
|
# @param descr [String] description for help
|
106
106
|
# @param to_check [Object] value to check
|
107
107
|
# @param type_list [NilClass, Class, Array[Class]] accepted value type(s)
|
108
|
+
# @param check_array [bool] set to true if it is a list of values to check
|
108
109
|
def validate_type(what, descr, to_check, type_list, check_array: false)
|
109
110
|
return nil if type_list.nil?
|
110
111
|
Aspera.assert(type_list.is_a?(Array) && type_list.all?(Class)){'types must be a Class Array'}
|
111
112
|
value_list = check_array ? to_check : [to_check]
|
112
113
|
value_list.each do |value|
|
113
114
|
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
|
+
"#{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
116
|
type_list.any?{|t|value.is_a?(t)}
|
116
117
|
end
|
117
118
|
end
|
@@ -181,7 +182,7 @@ module Aspera
|
|
181
182
|
|
182
183
|
# @param descr [String] description for help
|
183
184
|
# @param mandatory [Boolean] if true, raise error if option not set
|
184
|
-
# @param multiple [Boolean] if true, return remaining arguments
|
185
|
+
# @param multiple [Boolean] if true, return remaining arguments (Array)
|
185
186
|
# @param accept_list [Array] list of allowed values (Symbol)
|
186
187
|
# @param validation [Class, Array] accepted value type(s) or list of Symbols
|
187
188
|
# @param aliases [Hash] map of aliases: key = alias, value = real value
|
@@ -203,7 +204,7 @@ module Aspera
|
|
203
204
|
values = @unprocessed_cmd_line_arguments.shift(how_many)
|
204
205
|
values = values.map{|v|evaluate_extended_value(v, allowed_types)}
|
205
206
|
# 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
|
+
values = values.first if multiple && values.length.eql?(1) && values.first.is_a?(Array)
|
207
208
|
if accept_list
|
208
209
|
allowed_values = [].concat(accept_list)
|
209
210
|
allowed_values.concat(aliases.keys) unless aliases.nil?
|
@@ -500,7 +501,6 @@ module Aspera
|
|
500
501
|
self.class.multi_choice_assert(false, message, accept_list)
|
501
502
|
end
|
502
503
|
end
|
503
|
-
result = nil
|
504
504
|
sensitive = option && @declared_options[descr.to_sym].is_a?(Hash) && @declared_options[descr.to_sym][:sensitive]
|
505
505
|
default_prompt = "#{what}: #{descr}"
|
506
506
|
# ask interactively
|
data/lib/aspera/cli/plugin.rb
CHANGED
@@ -220,12 +220,12 @@ module Aspera
|
|
220
220
|
query = options.get_option(:query)
|
221
221
|
# dup default, as it could be frozen
|
222
222
|
query = default.dup if query.nil?
|
223
|
-
Log.log.debug{"
|
223
|
+
Log.log.debug{"query_read_delete=#{query}".bg_red}
|
224
224
|
begin
|
225
225
|
# check it is suitable
|
226
226
|
URI.encode_www_form(query) unless query.nil?
|
227
227
|
rescue StandardError => e
|
228
|
-
raise Cli::BadArgument, "Query must be an extended value which can be encoded with URI.encode_www_form. Refer to manual. (#{e.message})"
|
228
|
+
raise Cli::BadArgument, "Query must be an extended value (Hash, Array) which can be encoded with URI.encode_www_form. Refer to manual. (#{e.message})"
|
229
229
|
end
|
230
230
|
return query
|
231
231
|
end
|