aspera-cli 4.26.0 → 4.26.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 +0 -0
- data/CHANGELOG.md +17 -3
- data/lib/aspera/api/aoc.rb +2 -1
- data/lib/aspera/api/node.rb +2 -2
- data/lib/aspera/ascp/installation.rb +7 -4
- data/lib/aspera/assert.rb +17 -13
- data/lib/aspera/cli/extended_value.rb +6 -2
- data/lib/aspera/cli/formatter.rb +65 -60
- data/lib/aspera/cli/main.rb +69 -10
- data/lib/aspera/cli/manager.rb +130 -76
- data/lib/aspera/cli/options.schema.yaml +82 -0
- data/lib/aspera/cli/plugins/aoc.rb +36 -11
- data/lib/aspera/cli/plugins/base.rb +46 -37
- data/lib/aspera/cli/plugins/config.rb +9 -9
- data/lib/aspera/cli/plugins/faspex.rb +1 -1
- data/lib/aspera/cli/plugins/faspex5.rb +4 -5
- data/lib/aspera/cli/plugins/node.rb +1 -1
- data/lib/aspera/cli/sync_actions.rb +1 -1
- data/lib/aspera/cli/transfer_agent.rb +17 -15
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/command_line_builder.rb +22 -18
- data/lib/aspera/environment.rb +3 -3
- data/lib/aspera/formatter_interface.rb +14 -0
- data/lib/aspera/hash_ext.rb +6 -0
- data/lib/aspera/log.rb +4 -3
- data/lib/aspera/markdown.rb +4 -1
- data/lib/aspera/oauth/factory.rb +1 -1
- data/lib/aspera/proxy_auto_config.rb +3 -0
- data/lib/aspera/rest.rb +1 -1
- data/lib/aspera/schema/IBM Aspera Faspex API-5.0-enhanced.yaml +62801 -0
- data/lib/aspera/schema/IBM Aspera on Cloud API-0.2.6-enhanced.yaml +8898 -0
- data/lib/aspera/schema/documentation.rb +107 -0
- data/lib/aspera/schema/reader.rb +75 -0
- data/lib/aspera/schema/registry.rb +63 -0
- data/lib/aspera/sync/conf.schema.yaml +0 -26
- data/lib/aspera/sync/operations.rb +9 -5
- data/lib/aspera/transfer/faux_file.rb +1 -1
- data/lib/aspera/transfer/resumer.rb +1 -1
- data/lib/aspera/transfer/spec.rb +3 -3
- data/lib/aspera/transfer/spec.schema.yaml +1 -1
- data/lib/aspera/uri_reader.rb +1 -1
- data/lib/aspera/yaml.rb +4 -2
- data.tar.gz.sig +0 -0
- metadata +9 -3
- metadata.gz.sig +0 -0
- data/lib/aspera/transfer/spec_doc.rb +0 -76
data/lib/aspera/cli/main.rb
CHANGED
|
@@ -12,6 +12,8 @@ require 'aspera/cli/hints'
|
|
|
12
12
|
require 'aspera/secret_hider'
|
|
13
13
|
require 'aspera/log'
|
|
14
14
|
require 'aspera/assert'
|
|
15
|
+
require 'aspera/schema/documentation'
|
|
16
|
+
require 'aspera/schema/registry'
|
|
15
17
|
require 'net/ssh/errors'
|
|
16
18
|
require 'openssl'
|
|
17
19
|
|
|
@@ -19,6 +21,8 @@ module Aspera
|
|
|
19
21
|
module Cli
|
|
20
22
|
# Global objects shared with plugins
|
|
21
23
|
class Context
|
|
24
|
+
# @type [Array<Symbol>]
|
|
25
|
+
MEMBERS = %i[options transfer config formatter persistency man_header].freeze
|
|
22
26
|
# @!attribute [rw] options
|
|
23
27
|
# @return [Manager] the command line options manager
|
|
24
28
|
# @!attribute [rw] transfer
|
|
@@ -31,15 +35,17 @@ module Aspera
|
|
|
31
35
|
# @return [Object] # whatever the type is
|
|
32
36
|
# @!attribute [rw] man_header
|
|
33
37
|
# @return [Boolean] whether to display the manual header in plugin help
|
|
34
|
-
MEMBERS = %i[options transfer config formatter persistency man_header].freeze
|
|
35
38
|
attr_accessor(*MEMBERS)
|
|
36
39
|
|
|
37
40
|
# Initialize all members to nil, so that they are defined and can be validated later
|
|
41
|
+
# @return [nil]
|
|
38
42
|
def initialize
|
|
39
43
|
MEMBERS.each{ |i| instance_variable_set(:"@#{i}", nil)}
|
|
40
44
|
end
|
|
41
45
|
|
|
42
46
|
# Validate that all members are set, raise exception if not
|
|
47
|
+
# @raise [Aspera::AssertionError] if any member is not set
|
|
48
|
+
# @return [nil]
|
|
43
49
|
def validate
|
|
44
50
|
MEMBERS.each do |i|
|
|
45
51
|
Aspera.assert(instance_variable_defined?(:"@#{i}"))
|
|
@@ -47,10 +53,14 @@ module Aspera
|
|
|
47
53
|
end
|
|
48
54
|
end
|
|
49
55
|
|
|
56
|
+
# Check if the context is in manual-only mode
|
|
57
|
+
# @return [Boolean] true if in manual-only mode
|
|
50
58
|
def only_manual?
|
|
51
59
|
transfer.eql?(:only_manual)
|
|
52
60
|
end
|
|
53
61
|
|
|
62
|
+
# Set the context to manual-only mode
|
|
63
|
+
# @return [Symbol] :only_manual
|
|
54
64
|
def only_manual!
|
|
55
65
|
@transfer = :only_manual
|
|
56
66
|
end
|
|
@@ -69,26 +79,37 @@ module Aspera
|
|
|
69
79
|
private_constant :COMMAND_CONFIG, :COMMAND_HELP, :SCALAR_TYPES, :USER_INTERFACES
|
|
70
80
|
|
|
71
81
|
class << self
|
|
72
|
-
|
|
82
|
+
# Create a special result type (only used internally here)
|
|
83
|
+
# @param special_sym [Symbol] the special result type
|
|
84
|
+
# @return [Hash] result hash with type :special
|
|
85
|
+
def result_special(special_sym); {type: :special, data: special_sym}; end
|
|
73
86
|
|
|
74
87
|
# Expect some list, but nothing to display
|
|
88
|
+
# @return [Hash] result hash for empty list
|
|
75
89
|
def result_empty; result_special(:empty); end
|
|
76
90
|
|
|
77
91
|
# Nothing expected
|
|
92
|
+
# @return [Hash] result hash for nothing
|
|
78
93
|
def result_nothing; result_special(:nothing); end
|
|
79
94
|
|
|
80
95
|
# Result is some status, such as "complete", "deleted"...
|
|
81
96
|
# @param status [String] The status
|
|
97
|
+
# @return [Hash] result hash with type :status
|
|
82
98
|
def result_status(status); return {type: :status, data: status}; end
|
|
83
99
|
|
|
84
100
|
# Text result coming from command result
|
|
101
|
+
# @param data [String, Integer, Symbol] the text data to display
|
|
102
|
+
# @return [Hash] result hash with type :text
|
|
85
103
|
def result_text(data); return {type: :text, data: data}; end
|
|
86
104
|
|
|
105
|
+
# Create a success result
|
|
106
|
+
# @return [Hash] result hash with status 'complete'
|
|
87
107
|
def result_success; return result_status('complete'); end
|
|
88
108
|
|
|
89
109
|
# Process statuses of finished transfer sessions
|
|
90
|
-
# @
|
|
91
|
-
#
|
|
110
|
+
# @param statuses [Array] array of transfer session statuses
|
|
111
|
+
# @raise [Symbol] exception if there is one error
|
|
112
|
+
# @return [Hash] empty status result if all transfers succeeded
|
|
92
113
|
def result_transfer(statuses)
|
|
93
114
|
worst = TransferAgent.session_status(statuses)
|
|
94
115
|
raise worst unless worst.eql?(:success)
|
|
@@ -112,26 +133,33 @@ module Aspera
|
|
|
112
133
|
end
|
|
113
134
|
|
|
114
135
|
# Display image for that URL or directly blob
|
|
115
|
-
#
|
|
116
136
|
# @param url_or_blob [String] URL or blob to display as image
|
|
137
|
+
# @return [Hash] result hash with type :image
|
|
117
138
|
def result_image(url_or_blob)
|
|
118
139
|
return {type: :image, data: url_or_blob}
|
|
119
140
|
end
|
|
120
141
|
|
|
121
142
|
# A single object, must be Hash
|
|
143
|
+
# @param data [Hash] the object data
|
|
144
|
+
# @param fields [Array<String>, nil] optional list of fields to display
|
|
145
|
+
# @return [Hash] result hash with type :single_object
|
|
122
146
|
def result_single_object(data, fields: nil)
|
|
123
147
|
return {type: :single_object, data: data, fields: fields}
|
|
124
148
|
end
|
|
125
149
|
|
|
126
150
|
# An Array of Hash
|
|
151
|
+
# @param data [Array<Hash>] array of objects
|
|
152
|
+
# @param fields [Array<String>, nil] optional list of fields to display
|
|
153
|
+
# @param total [Integer, nil] optional total count
|
|
154
|
+
# @return [Hash] result hash with type :object_list
|
|
127
155
|
def result_object_list(data, fields: nil, total: nil)
|
|
128
156
|
return {type: :object_list, data: data, fields: fields, total: total}
|
|
129
157
|
end
|
|
130
158
|
|
|
131
159
|
# A list of values
|
|
132
|
-
#
|
|
133
160
|
# @param data [Array] The list of values
|
|
134
161
|
# @param name [String] The name of the list (used for display)
|
|
162
|
+
# @return [Hash] result hash with type :value_list
|
|
135
163
|
def result_value_list(data, name: 'id')
|
|
136
164
|
Aspera.assert_type(data, Array)
|
|
137
165
|
Aspera.assert_type(name, String)
|
|
@@ -139,6 +167,8 @@ module Aspera
|
|
|
139
167
|
end
|
|
140
168
|
|
|
141
169
|
# Determines type of result based on data
|
|
170
|
+
# @param data [Object] the data to analyze and format
|
|
171
|
+
# @return [Hash] result hash with appropriate type based on data
|
|
142
172
|
def result_auto(data)
|
|
143
173
|
case data
|
|
144
174
|
when NilClass
|
|
@@ -159,6 +189,8 @@ module Aspera
|
|
|
159
189
|
end
|
|
160
190
|
|
|
161
191
|
# Minimum initialization, no exception raised
|
|
192
|
+
# @param argv [Array<String>] command line arguments
|
|
193
|
+
# @return [nil]
|
|
162
194
|
def initialize(argv)
|
|
163
195
|
@argv = argv
|
|
164
196
|
Log.dump(:argv, @argv, level: :trace2)
|
|
@@ -169,6 +201,8 @@ module Aspera
|
|
|
169
201
|
end
|
|
170
202
|
|
|
171
203
|
# This is the main function called by initial script just after constructor
|
|
204
|
+
# Processes command line arguments, executes commands, and handles exceptions
|
|
205
|
+
# @return [nil]
|
|
172
206
|
def process_command_line
|
|
173
207
|
# Catch exception information , if any
|
|
174
208
|
exception_info = nil
|
|
@@ -239,6 +273,7 @@ module Aspera
|
|
|
239
273
|
rescue Cli::BadArgument => e; exception_info = {e: e, t: 'Argument', usage: true}
|
|
240
274
|
rescue Cli::MissingArgument => e; exception_info = {e: e, t: 'Missing', usage: true}
|
|
241
275
|
rescue Cli::BadIdentifier => e; exception_info = {e: e, t: 'Identifier'}
|
|
276
|
+
rescue Cli::SchemaRequest => e; exception_info = {e: e, t: 'Schema'}
|
|
242
277
|
rescue Cli::Error => e; exception_info = {e: e, t: 'Tool', usage: true}
|
|
243
278
|
rescue Transfer::Error => e; exception_info = {e: e, t: 'Transfer'}
|
|
244
279
|
rescue RestCallError => e; exception_info = {e: e, t: 'Rest'}
|
|
@@ -251,11 +286,22 @@ module Aspera
|
|
|
251
286
|
# 1- processing of error condition
|
|
252
287
|
unless exception_info.nil?
|
|
253
288
|
Log.log.warn(exception_info[:e].message) if Log.instance.logger_type.eql?(:syslog) && exception_info[:security]
|
|
254
|
-
Log.log.error{"#{exception_info[:t]}: #{exception_info[:e].message}"}
|
|
289
|
+
Log.log.error{"#{exception_info[:t]}: #{exception_info[:e].message}"} unless exception_info[:e].is_a?(Cli::SchemaRequest)
|
|
255
290
|
Log.log.debug{(['Backtrace:'] + exception_info[:e].backtrace).join("\n")} if exception_info[:debug]
|
|
256
291
|
@context.formatter.display_message(:error, 'Use option -h to get help.') if exception_info[:usage]
|
|
257
292
|
# Is that a known error condition with proposal for remediation ?
|
|
258
293
|
Hints.hint_for(exception_info[:e], @context.formatter)
|
|
294
|
+
# Requested help for a Hash parameter/option ?
|
|
295
|
+
if exception_info[:e].is_a?(Cli::SchemaRequest)
|
|
296
|
+
Log.log.info{"#{exception_info[:t]}: #{exception_info[:e].message}"}
|
|
297
|
+
schema_path = exception_info[:e].path
|
|
298
|
+
if schema_path.nil?
|
|
299
|
+
Log.log.warn{'Sorry, no schema provided yet. Please refer to the manual or API.'}
|
|
300
|
+
else
|
|
301
|
+
builder = Schema::Documentation.new(TerminalFormatter, Schema::Registry.instance.reader(schema_path)).build
|
|
302
|
+
@context.formatter.display_results(**Main.result_object_list(builder.rows, fields: builder.columns))
|
|
303
|
+
end
|
|
304
|
+
end
|
|
259
305
|
end
|
|
260
306
|
# 2- processing of command not processed (due to exception or bad command line)
|
|
261
307
|
if execute_command || @option_show_config
|
|
@@ -276,6 +322,10 @@ module Aspera
|
|
|
276
322
|
return
|
|
277
323
|
end
|
|
278
324
|
|
|
325
|
+
# Display usage information and help
|
|
326
|
+
# @param all [Boolean] if true, show help for all plugins; if false, show only current plugin
|
|
327
|
+
# @param exit [Boolean] if true, exit the process after displaying help
|
|
328
|
+
# @return [nil]
|
|
279
329
|
def show_usage(all: true, exit: true)
|
|
280
330
|
# Display main plugin options (+config)
|
|
281
331
|
@context.formatter.display_message(:error, @context.options.parser)
|
|
@@ -298,7 +348,10 @@ module Aspera
|
|
|
298
348
|
|
|
299
349
|
private
|
|
300
350
|
|
|
351
|
+
# Initialize agents and options
|
|
301
352
|
# This can throw exception if there is a problem with the environment, needs to be caught by execute method
|
|
353
|
+
# @raise [StandardError] if there is a problem with the environment
|
|
354
|
+
# @return [nil]
|
|
302
355
|
def init_agents_and_options
|
|
303
356
|
@context.man_header = true
|
|
304
357
|
# Create formatter, in case there is an exception, it is used to display.
|
|
@@ -328,6 +381,8 @@ module Aspera
|
|
|
328
381
|
@context.options.parser.banner = app_banner
|
|
329
382
|
end
|
|
330
383
|
|
|
384
|
+
# Generate the application banner for help display
|
|
385
|
+
# @return [String] formatted banner text
|
|
331
386
|
def app_banner
|
|
332
387
|
t = ' ' * 8
|
|
333
388
|
return <<~END_OF_BANNER
|
|
@@ -362,7 +417,8 @@ module Aspera
|
|
|
362
417
|
END_OF_BANNER
|
|
363
418
|
end
|
|
364
419
|
|
|
365
|
-
# Define header for manual
|
|
420
|
+
# Define header for manual and declare all global options
|
|
421
|
+
# @return [nil]
|
|
366
422
|
def declare_global_options
|
|
367
423
|
Log.log.debug('declare_global_options')
|
|
368
424
|
@context.options.declare(:help, 'Show this message', allowed: Allowed::TYPES_NONE, short: 'h'){@option_help = true}
|
|
@@ -397,9 +453,10 @@ module Aspera
|
|
|
397
453
|
@context.options.parse_options!
|
|
398
454
|
end
|
|
399
455
|
|
|
400
|
-
#
|
|
456
|
+
# Get the plugin instance based on name
|
|
401
457
|
# Also loads the plugin options, and default values from conf file
|
|
402
|
-
# @param plugin_name_sym
|
|
458
|
+
# @param plugin_name_sym [Symbol] symbol for plugin name
|
|
459
|
+
# @return [Plugins::Base] the plugin instance
|
|
403
460
|
def get_plugin_instance_with_options(plugin_name_sym)
|
|
404
461
|
Log.log.debug{"get_plugin_instance_with_options(#{plugin_name_sym})"}
|
|
405
462
|
# Load default params only if no param already loaded before plugin instantiation
|
|
@@ -408,6 +465,8 @@ module Aspera
|
|
|
408
465
|
return command_plugin
|
|
409
466
|
end
|
|
410
467
|
|
|
468
|
+
# Generate bash completion suggestions
|
|
469
|
+
# @return [nil]
|
|
411
470
|
def generate_bash_completion
|
|
412
471
|
if @context.options.get_next_argument('', multiple: true, mandatory: false).nil?
|
|
413
472
|
Plugins::Factory.instance.plugin_list.each{ |p| puts p}
|