aspera-cli 4.24.2 → 4.25.0.pre
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.
Potentially problematic release.
This version of aspera-cli might be problematic. Click here for more details.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +1064 -758
- data/CONTRIBUTING.md +43 -100
- data/README.md +671 -419
- data/lib/aspera/api/aoc.rb +71 -43
- data/lib/aspera/api/cos_node.rb +3 -2
- data/lib/aspera/api/faspex.rb +6 -5
- data/lib/aspera/api/node.rb +10 -12
- data/lib/aspera/ascmd.rb +1 -2
- data/lib/aspera/ascp/installation.rb +53 -39
- data/lib/aspera/assert.rb +25 -3
- data/lib/aspera/cli/error.rb +4 -2
- data/lib/aspera/cli/extended_value.rb +84 -60
- data/lib/aspera/cli/formatter.rb +55 -22
- data/lib/aspera/cli/main.rb +21 -14
- data/lib/aspera/cli/manager.rb +348 -247
- data/lib/aspera/cli/plugins/alee.rb +3 -3
- data/lib/aspera/cli/plugins/aoc.rb +70 -14
- data/lib/aspera/cli/plugins/base.rb +57 -49
- data/lib/aspera/cli/plugins/config.rb +69 -84
- data/lib/aspera/cli/plugins/console.rb +13 -8
- data/lib/aspera/cli/plugins/cos.rb +1 -1
- data/lib/aspera/cli/plugins/faspex.rb +32 -26
- data/lib/aspera/cli/plugins/faspex5.rb +45 -43
- data/lib/aspera/cli/plugins/faspio.rb +5 -5
- data/lib/aspera/cli/plugins/httpgw.rb +1 -1
- data/lib/aspera/cli/plugins/node.rb +131 -120
- data/lib/aspera/cli/plugins/oauth.rb +1 -1
- data/lib/aspera/cli/plugins/orchestrator.rb +114 -32
- data/lib/aspera/cli/plugins/preview.rb +26 -46
- data/lib/aspera/cli/plugins/server.rb +6 -8
- data/lib/aspera/cli/plugins/shares.rb +27 -32
- data/lib/aspera/cli/sync_actions.rb +49 -38
- data/lib/aspera/cli/transfer_agent.rb +16 -34
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +8 -5
- data/lib/aspera/command_line_builder.rb +20 -17
- data/lib/aspera/coverage.rb +1 -1
- data/lib/aspera/environment.rb +41 -34
- data/lib/aspera/faspex_gw.rb +1 -1
- data/lib/aspera/keychain/factory.rb +1 -2
- data/lib/aspera/markdown.rb +31 -0
- data/lib/aspera/nagios.rb +6 -5
- data/lib/aspera/oauth/base.rb +17 -27
- data/lib/aspera/oauth/factory.rb +1 -1
- data/lib/aspera/oauth/url_json.rb +2 -1
- data/lib/aspera/preview/file_types.rb +23 -37
- data/lib/aspera/products/connect.rb +3 -3
- data/lib/aspera/rest.rb +51 -39
- data/lib/aspera/rest_error_analyzer.rb +4 -4
- data/lib/aspera/ssh.rb +5 -2
- data/lib/aspera/ssl.rb +41 -0
- data/lib/aspera/sync/conf.schema.yaml +182 -34
- data/lib/aspera/sync/database.rb +2 -1
- data/lib/aspera/sync/operations.rb +125 -69
- data/lib/aspera/transfer/parameters.rb +3 -4
- data/lib/aspera/transfer/spec.rb +2 -3
- data/lib/aspera/transfer/spec.schema.yaml +48 -18
- data/lib/aspera/transfer/spec_doc.rb +14 -14
- data/lib/aspera/uri_reader.rb +1 -1
- data/lib/transferd_pb.rb +2 -2
- data.tar.gz.sig +0 -0
- metadata +19 -6
- metadata.gz.sig +3 -2
|
@@ -17,16 +17,8 @@ module Aspera
|
|
|
17
17
|
class ExtendedValue
|
|
18
18
|
include Singleton
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
MARKER_IN_END = '@'
|
|
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
|
|
20
|
+
# First is default
|
|
21
|
+
DEFAULT_DECODERS = %i[none json ruby yaml]
|
|
30
22
|
|
|
31
23
|
class << self
|
|
32
24
|
# Decode comma separated table text
|
|
@@ -45,8 +37,32 @@ module Aspera
|
|
|
45
37
|
return hash_array
|
|
46
38
|
end
|
|
47
39
|
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
# JSON Parser, with more information on error location
|
|
41
|
+
# extract a context: 10 chars before and after the error on the given line and display a pointer "^"
|
|
42
|
+
# :reek:UncommunicativeMethodName
|
|
43
|
+
def JSON_parse(value) # rubocop:disable Naming/MethodName
|
|
44
|
+
JSON.parse(value)
|
|
45
|
+
rescue JSON::ParserError => e
|
|
46
|
+
m = /at line (\d+) column (\d+)/.match(e.message)
|
|
47
|
+
raise if m.nil?
|
|
48
|
+
line = m[1].to_i - 1
|
|
49
|
+
column = m[2].to_i - 1
|
|
50
|
+
lines = value.lines
|
|
51
|
+
raise if line >= lines.size
|
|
52
|
+
error_line = lines[line].chomp
|
|
53
|
+
context_col_beg = [column - 10, 0].max
|
|
54
|
+
context_col_end = [column + 10, error_line.length].min
|
|
55
|
+
context = error_line[context_col_beg...context_col_end]
|
|
56
|
+
cursor_pos = column - context_col_beg
|
|
57
|
+
pointer = ' ' * cursor_pos + '^'.blink
|
|
58
|
+
raise BadArgument, "#{e.message}\n#{context}\n#{pointer}"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# The value must be empty
|
|
62
|
+
# @param value [String] The value as parameter
|
|
63
|
+
# @param ext_type [Symbol] The method of extended value
|
|
64
|
+
def assert_no_value(value, ext_type)
|
|
65
|
+
Aspera.assert(value.empty?, type: BadArgument){"no value allowed for extended value type: #{ext_type}"}
|
|
50
66
|
end
|
|
51
67
|
end
|
|
52
68
|
|
|
@@ -54,7 +70,8 @@ module Aspera
|
|
|
54
70
|
|
|
55
71
|
def initialize
|
|
56
72
|
# Base handlers
|
|
57
|
-
# Other handlers can be set using
|
|
73
|
+
# Other handlers can be set using `on`
|
|
74
|
+
# e.g. `preset` is reader in config plugin
|
|
58
75
|
@handlers = {
|
|
59
76
|
val: lambda{ |i| i},
|
|
60
77
|
base64: lambda{ |i| Base64.decode64(i)},
|
|
@@ -62,7 +79,7 @@ module Aspera
|
|
|
62
79
|
env: lambda{ |i| ENV.fetch(i, nil)},
|
|
63
80
|
file: lambda{ |i| File.read(File.expand_path(i))},
|
|
64
81
|
uri: lambda{ |i| UriReader.read(i)},
|
|
65
|
-
json: lambda{ |i| JSON_parse(i)},
|
|
82
|
+
json: lambda{ |i| ExtendedValue.JSON_parse(i)},
|
|
66
83
|
lines: lambda{ |i| i.split("\n")},
|
|
67
84
|
list: lambda{ |i| i[1..-1].split(i[0])},
|
|
68
85
|
none: lambda{ |i| ExtendedValue.assert_no_value(i, :none); nil}, # rubocop:disable Style/Semicolon
|
|
@@ -74,63 +91,60 @@ module Aspera
|
|
|
74
91
|
stdbin: lambda{ |i| ExtendedValue.assert_no_value(i, :stdbin); $stdin.binmode.read}, # rubocop:disable Style/Semicolon
|
|
75
92
|
yaml: lambda{ |i| YAML.load(i)},
|
|
76
93
|
zlib: lambda{ |i| Zlib::Inflate.inflate(i)},
|
|
77
|
-
extend: lambda{ |i| ExtendedValue.instance.
|
|
94
|
+
extend: lambda{ |i| ExtendedValue.instance.evaluate_extend(i)}
|
|
78
95
|
}
|
|
96
|
+
@regex_single = nil
|
|
97
|
+
@regex_extend = nil
|
|
79
98
|
@default_decoder = nil
|
|
99
|
+
update_regex
|
|
80
100
|
end
|
|
81
101
|
|
|
82
|
-
# Regex to match an extended value
|
|
83
|
-
def
|
|
84
|
-
"#{MARKER_START}(#{modifiers.join('|')})#{MARKER_END}"
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
# JSON Parser, with more information on error location
|
|
88
|
-
# :reek:UncommunicativeMethodName
|
|
89
|
-
def JSON_parse(value) # rubocop:disable Naming/MethodName
|
|
90
|
-
JSON.parse(value)
|
|
91
|
-
rescue JSON::ParserError => e
|
|
92
|
-
m = /at line (\d+) column (\d+)/.match(e.message)
|
|
93
|
-
raise if m.nil?
|
|
94
|
-
line = m[1].to_i - 1
|
|
95
|
-
column = m[2].to_i - 1
|
|
96
|
-
lines = value.lines
|
|
97
|
-
raise if line >= lines.size
|
|
98
|
-
error_line = lines[line].chomp
|
|
99
|
-
context_col_beg = [column - 10, 0].max
|
|
100
|
-
context_col_end = [column + 10, error_line.length].min
|
|
101
|
-
context = error_line[context_col_beg...context_col_end]
|
|
102
|
-
cursor_pos = column - context_col_beg
|
|
103
|
-
pointer = ' ' * cursor_pos + '^'.blink
|
|
104
|
-
raise BadArgument, "#{e.message}\n#{context}\n#{pointer}"
|
|
102
|
+
# Update the Regex to match an extended value based on @handlers
|
|
103
|
+
def update_regex
|
|
104
|
+
handler_regex = "#{MARKER_START}(#{modifiers.join('|')})#{MARKER_END}"
|
|
105
|
+
@regex_single = Regexp.new("^#{handler_regex}(.*)$", Regexp::MULTILINE)
|
|
106
|
+
@regex_extend = Regexp.new("^(.*)#{handler_regex}([^#{MARKER_IN_END}]*)#{MARKER_IN_END}(.*)$", Regexp::MULTILINE)
|
|
105
107
|
end
|
|
106
108
|
|
|
107
109
|
public
|
|
108
110
|
|
|
111
|
+
attr_reader :default_decoder
|
|
112
|
+
|
|
109
113
|
def default_decoder=(value)
|
|
110
114
|
Log.log.debug{"Setting default decoder to (#{value.class}) #{value}"}
|
|
111
|
-
Aspera.
|
|
115
|
+
Aspera.assert_values(value, DEFAULT_DECODERS)
|
|
116
|
+
value = nil if value.eql?(:none)
|
|
112
117
|
@default_decoder = value
|
|
113
118
|
end
|
|
114
119
|
|
|
120
|
+
# List of Extended Value methods
|
|
115
121
|
def modifiers; @handlers.keys; end
|
|
116
122
|
|
|
117
123
|
# Add a new handler
|
|
118
|
-
def
|
|
119
|
-
Log.log.debug{"setting handler for #{name}"}
|
|
124
|
+
def on(name, &block)
|
|
120
125
|
Aspera.assert_type(name, Symbol){'name'}
|
|
121
|
-
|
|
126
|
+
Aspera.assert(block)
|
|
127
|
+
Log.log.debug{"Setting handler for #{name}"}
|
|
128
|
+
@handlers[name] = block
|
|
129
|
+
update_regex
|
|
122
130
|
end
|
|
123
131
|
|
|
124
|
-
#
|
|
125
|
-
#
|
|
126
|
-
#
|
|
127
|
-
# @param
|
|
128
|
-
|
|
132
|
+
# Parses a `String` value to extended value.
|
|
133
|
+
# If it is a String using supported extended value modifiers, then evaluate them.
|
|
134
|
+
# Other value types are returned as is.
|
|
135
|
+
# @param value [String] the value to parse
|
|
136
|
+
# @param context [String] Context in which evaluation is done
|
|
137
|
+
# @param allowed [Array<Class>,NilClass] Expected types
|
|
138
|
+
# @return [Object] Evaluated value
|
|
139
|
+
def evaluate(value, context:, allowed: nil)
|
|
129
140
|
return value unless value.is_a?(String)
|
|
130
|
-
|
|
141
|
+
Aspera.assert_array_all(allowed, Class) unless allowed.nil?
|
|
142
|
+
# use default decoder if not an extended value and expect complex types
|
|
143
|
+
using_default_decoder = allowed&.all?{ |t| DEFAULT_PARSER_TYPES.include?(t)} && !@regex_single.match?(value) && !@default_decoder.nil?
|
|
144
|
+
value = [MARKER_START, @default_decoder, MARKER_END, value].join if using_default_decoder
|
|
131
145
|
# First determine decoders, in reversed order
|
|
132
146
|
handlers_reversed = []
|
|
133
|
-
while (m = value.match(
|
|
147
|
+
while (m = value.match(@regex_single))
|
|
134
148
|
handler = m[1].to_sym
|
|
135
149
|
handlers_reversed.unshift(handler)
|
|
136
150
|
value = m[2]
|
|
@@ -139,27 +153,37 @@ module Aspera
|
|
|
139
153
|
Log.log.trace1{"evaluating: #{handlers_reversed}, value: #{value}"}
|
|
140
154
|
handlers_reversed.each do |handler|
|
|
141
155
|
value = @handlers[handler].call(value)
|
|
156
|
+
rescue => e
|
|
157
|
+
raise BadArgument, "Evaluation of #{handler} for #{context}: #{e.message}"
|
|
142
158
|
end
|
|
143
159
|
return value
|
|
144
160
|
end
|
|
145
161
|
|
|
146
|
-
# Parse string value as extended value
|
|
147
|
-
# Use default decoder if none is specified
|
|
148
|
-
def evaluate_with_default(value)
|
|
149
|
-
value = [MARKER_START, @default_decoder, MARKER_END, value].join if value.is_a?(String) && value.match(/^#{handler_regex_string}.*$/).nil? && !@default_decoder.nil?
|
|
150
|
-
return evaluate(value)
|
|
151
|
-
end
|
|
152
|
-
|
|
153
162
|
# Find inner extended values
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
while (m = value.match(
|
|
163
|
+
# Only used in above lambda
|
|
164
|
+
def evaluate_extend(value)
|
|
165
|
+
while (m = value.match(@regex_extend))
|
|
157
166
|
sub_value = "@#{m[2]}:#{m[3]}"
|
|
158
167
|
Log.log.debug{"evaluating #{sub_value}"}
|
|
159
|
-
value = "#{m[1]}#{evaluate(sub_value)}#{m[4]}"
|
|
168
|
+
value = "#{m[1]}#{evaluate(sub_value, context: 'composite extended value')}#{m[4]}"
|
|
160
169
|
end
|
|
161
170
|
return value
|
|
162
171
|
end
|
|
172
|
+
# marker "@"
|
|
173
|
+
MARKER_START = '@'
|
|
174
|
+
# marker ":"
|
|
175
|
+
MARKER_END = ':'
|
|
176
|
+
# marker "@"
|
|
177
|
+
MARKER_IN_END = '@'
|
|
178
|
+
|
|
179
|
+
# Special handlers stop processing of handlers on right
|
|
180
|
+
# :extend includes processing of other handlers in itself
|
|
181
|
+
# :val keeps the value intact
|
|
182
|
+
SPECIAL_HANDLERS = %i[extend val].freeze
|
|
183
|
+
|
|
184
|
+
# Array and Hash types:
|
|
185
|
+
DEFAULT_PARSER_TYPES = [Array, Hash].freeze
|
|
186
|
+
private_constant :MARKER_START, :MARKER_END, :MARKER_IN_END, :SPECIAL_HANDLERS, :DEFAULT_PARSER_TYPES
|
|
163
187
|
end
|
|
164
188
|
end
|
|
165
189
|
end
|
data/lib/aspera/cli/formatter.rb
CHANGED
|
@@ -7,6 +7,7 @@ require 'aspera/secret_hider'
|
|
|
7
7
|
require 'aspera/environment'
|
|
8
8
|
require 'aspera/log'
|
|
9
9
|
require 'aspera/assert'
|
|
10
|
+
require 'aspera/markdown'
|
|
10
11
|
require 'terminal-table'
|
|
11
12
|
require 'tty-spinner'
|
|
12
13
|
require 'yaml'
|
|
@@ -64,8 +65,23 @@ module Aspera
|
|
|
64
65
|
end
|
|
65
66
|
|
|
66
67
|
# used by spec_doc
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
# @param match [MatchData,String]
|
|
69
|
+
def markdown(match)
|
|
70
|
+
if match.is_a?(String)
|
|
71
|
+
match = Markdown::FORMATS.match(match)
|
|
72
|
+
Aspera.assert(match)
|
|
73
|
+
end
|
|
74
|
+
Aspera.assert_type(match, MatchData)
|
|
75
|
+
if match[:entity]
|
|
76
|
+
Aspera.assert_values(match[:entity], 'bsol')
|
|
77
|
+
'\\'
|
|
78
|
+
elsif match[:bold]
|
|
79
|
+
match[:bold].to_s.blue
|
|
80
|
+
elsif match[:code]
|
|
81
|
+
match[:code].to_s.bold
|
|
82
|
+
else
|
|
83
|
+
Aspera.error_unexpected_value(match.to_s)
|
|
84
|
+
end
|
|
69
85
|
end
|
|
70
86
|
|
|
71
87
|
# replace empty values with a readable version on terminal
|
|
@@ -100,30 +116,49 @@ module Aspera
|
|
|
100
116
|
end
|
|
101
117
|
end
|
|
102
118
|
|
|
119
|
+
# Given a list of string, display that list in a single cell
|
|
120
|
+
def list_to_string(list)
|
|
121
|
+
list.join(',')
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Build new prefix
|
|
125
|
+
def add_prefix(prefix, key)
|
|
126
|
+
[prefix, key].compact.join('.')
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Add elements of enumerator to the stack, in reverse order
|
|
130
|
+
def add_elements(stack, prefix, enum)
|
|
131
|
+
enum.reverse_each do |key, value|
|
|
132
|
+
stack.push([add_prefix(prefix, key), value])
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
103
136
|
# Flatten a Hash into single level hash
|
|
104
137
|
def flatten_hash(input)
|
|
105
138
|
Aspera.assert_type(input, Hash)
|
|
106
139
|
return input if input.empty?
|
|
107
140
|
flat = {}
|
|
141
|
+
# tail (pop,push) contains the next element to display
|
|
108
142
|
stack = [[nil, input]]
|
|
109
143
|
until stack.empty?
|
|
110
144
|
prefix, current = stack.pop
|
|
145
|
+
# empty things will be displayed as such
|
|
111
146
|
if current.respond_to?(:empty?) && current.empty?
|
|
112
147
|
flat[prefix] = current
|
|
113
148
|
next
|
|
114
149
|
end
|
|
115
150
|
case current
|
|
116
151
|
when Hash
|
|
117
|
-
|
|
152
|
+
add_elements(stack, prefix, current)
|
|
118
153
|
when Array
|
|
119
|
-
if current.
|
|
120
|
-
flat[prefix] = current.
|
|
154
|
+
if current.none?{ |i| i.is_a?(Array) || i.is_a?(Hash)}
|
|
155
|
+
flat[prefix] = list_to_string(current.map(&:to_s))
|
|
121
156
|
elsif current.all?{ |i| i.is_a?(Hash) && i.keys == ['name']}
|
|
122
|
-
flat[prefix] = current.map{ |i| i['name']}
|
|
157
|
+
flat[prefix] = list_to_string(current.map{ |i| i['name']})
|
|
123
158
|
elsif current.all?{ |i| i.is_a?(Hash) && i.keys.sort == %w[name value]}
|
|
124
|
-
stack
|
|
159
|
+
add_elements(stack, prefix, current.each_with_object({}){ |i, h| h[i['name']] = i['value']})
|
|
125
160
|
else
|
|
126
|
-
current.each_with_index.
|
|
161
|
+
add_elements(stack, prefix, current.each_with_index.map{ |v, i| [i, v]})
|
|
127
162
|
end
|
|
128
163
|
else
|
|
129
164
|
flat[prefix] = current
|
|
@@ -166,23 +201,23 @@ module Aspera
|
|
|
166
201
|
else
|
|
167
202
|
{}
|
|
168
203
|
end
|
|
169
|
-
options.declare(:format, 'Output format',
|
|
170
|
-
options.declare(:output, 'Destination for results',
|
|
171
|
-
options.declare(:display, 'Output only some information',
|
|
204
|
+
options.declare(:format, 'Output format', allowed: DISPLAY_FORMATS, handler: {o: self, m: :option_handler}, default: :table)
|
|
205
|
+
options.declare(:output, 'Destination for results', handler: {o: self, m: :option_handler})
|
|
206
|
+
options.declare(:display, 'Output only some information', allowed: DISPLAY_LEVELS, handler: {o: self, m: :option_handler}, default: :info)
|
|
172
207
|
options.declare(
|
|
173
208
|
:fields, "Comma separated list of: fields, or #{SpecialValues::ALL}, or #{SpecialValues::DEF}", handler: {o: self, m: :option_handler},
|
|
174
|
-
|
|
209
|
+
allowed: [String, Array, Regexp, Proc],
|
|
175
210
|
default: SpecialValues::DEF
|
|
176
211
|
)
|
|
177
|
-
options.declare(:select, 'Select only some items in lists: column, value',
|
|
178
|
-
options.declare(:table_style, '(Table) Display style',
|
|
179
|
-
options.declare(:flat_hash, '(Table) Display deep values as additional keys',
|
|
212
|
+
options.declare(:select, 'Select only some items in lists: column, value', allowed: [Hash, Proc], handler: {o: self, m: :option_handler})
|
|
213
|
+
options.declare(:table_style, '(Table) Display style', allowed: [Hash], handler: {o: self, m: :option_handler}, default: default_table_style)
|
|
214
|
+
options.declare(:flat_hash, '(Table) Display deep values as additional keys', allowed: Allowed::TYPES_BOOLEAN, handler: {o: self, m: :option_handler}, default: true)
|
|
180
215
|
options.declare(
|
|
181
|
-
:multi_single, '(Table) Control how object list is displayed as single table, or multiple objects',
|
|
216
|
+
:multi_single, '(Table) Control how object list is displayed as single table, or multiple objects', allowed: %i[no yes single],
|
|
182
217
|
handler: {o: self, m: :option_handler}, default: :no
|
|
183
218
|
)
|
|
184
|
-
options.declare(:show_secrets, 'Show secrets on command output',
|
|
185
|
-
options.declare(:image, 'Options for image display',
|
|
219
|
+
options.declare(:show_secrets, 'Show secrets on command output', allowed: Allowed::TYPES_BOOLEAN, handler: {o: self, m: :option_handler}, default: false)
|
|
220
|
+
options.declare(:image, 'Options for image display', allowed: Hash, handler: {o: self, m: :option_handler}, default: {})
|
|
186
221
|
end
|
|
187
222
|
|
|
188
223
|
# method accessed by option manager
|
|
@@ -326,8 +361,7 @@ module Aspera
|
|
|
326
361
|
end
|
|
327
362
|
when :object_list
|
|
328
363
|
# :object_list is an Array of Hash, where key=column name
|
|
329
|
-
Aspera.
|
|
330
|
-
Aspera.assert(data.all?(Hash)){"expecting Array of Hash: #{data.inspect}"}
|
|
364
|
+
Aspera.assert_array_all(data, Hash){'result'}
|
|
331
365
|
data = data.map{ |obj| self.class.flatten_hash(obj)} if @options[:flat_hash]
|
|
332
366
|
display_table(data, compute_fields(data, fields), single: type.eql?(:single_object))
|
|
333
367
|
when :value_list
|
|
@@ -406,8 +440,7 @@ module Aspera
|
|
|
406
440
|
def filter_list_on_fields(data)
|
|
407
441
|
# by default, keep all data intact
|
|
408
442
|
return data if @options[:fields].eql?(SpecialValues::DEF) && @options[:select].nil?
|
|
409
|
-
Aspera.
|
|
410
|
-
Aspera.assert(data.all?(Hash)){'Filtering fields or select requires result is an Array of Hash'}
|
|
443
|
+
Aspera.assert_array_all(data, Hash){'filter or select'}
|
|
411
444
|
filter_columns_on_select(data)
|
|
412
445
|
return data if @options[:fields].eql?(SpecialValues::DEF)
|
|
413
446
|
selected_fields = compute_fields(data, @options[:fields])
|
data/lib/aspera/cli/main.rb
CHANGED
|
@@ -214,6 +214,7 @@ module Aspera
|
|
|
214
214
|
rescue Net::SSH::AuthenticationFailed => e; exception_info = {e: e, t: 'SSH', security: true}
|
|
215
215
|
rescue OpenSSL::SSL::SSLError => e; exception_info = {e: e, t: 'SSL'}
|
|
216
216
|
rescue Cli::BadArgument => e; exception_info = {e: e, t: 'Argument', usage: true}
|
|
217
|
+
rescue Cli::MissingArgument => e; exception_info = {e: e, t: 'Missing', usage: true}
|
|
217
218
|
rescue Cli::BadIdentifier => e; exception_info = {e: e, t: 'Identifier'}
|
|
218
219
|
rescue Cli::Error => e; exception_info = {e: e, t: 'Tool', usage: true}
|
|
219
220
|
rescue Transfer::Error => e; exception_info = {e: e, t: 'Transfer'}
|
|
@@ -228,6 +229,7 @@ module Aspera
|
|
|
228
229
|
unless exception_info.nil?
|
|
229
230
|
Log.log.warn(exception_info[:e].message) if Log.instance.logger_type.eql?(:syslog) && exception_info[:security]
|
|
230
231
|
@context.formatter.display_message(:error, "#{Formatter::ERROR_FLASH} #{exception_info[:t]}: #{exception_info[:e].message}")
|
|
232
|
+
Log.log.debug{(['Backtrace:'] + exception_info[:e].backtrace).join("\n")} if exception_info[:debug]
|
|
231
233
|
@context.formatter.display_message(:error, 'Use option -h to get help.') if exception_info[:usage]
|
|
232
234
|
# Is that a known error condition with proposal for remediation ?
|
|
233
235
|
Hints.hint_for(exception_info[:e], @context.formatter)
|
|
@@ -287,7 +289,6 @@ module Aspera
|
|
|
287
289
|
@context.options = Manager.new(Info::CMD_NAME, @argv)
|
|
288
290
|
# Formatter adds options
|
|
289
291
|
@context.formatter.declare_options(@context.options)
|
|
290
|
-
ExtendedValue.instance.default_decoder = @context.options.get_option(:struct_parser)
|
|
291
292
|
# Compare $0 with expected name
|
|
292
293
|
current_prog_name = File.basename($PROGRAM_NAME)
|
|
293
294
|
@context.formatter.display_message(
|
|
@@ -349,28 +350,34 @@ module Aspera
|
|
|
349
350
|
# Define header for manual
|
|
350
351
|
def declare_global_options
|
|
351
352
|
Log.log.debug('declare_global_options')
|
|
352
|
-
@context.options.declare(:help, 'Show this message',
|
|
353
|
-
@context.options.declare(:bash_comp, 'Generate bash completion for command',
|
|
354
|
-
@context.options.declare(:show_config, 'Display parameters used for the provided action',
|
|
355
|
-
@context.options.declare(:version, 'Display version',
|
|
353
|
+
@context.options.declare(:help, 'Show this message', allowed: Allowed::TYPES_NONE, short: 'h'){@option_help = true}
|
|
354
|
+
@context.options.declare(:bash_comp, 'Generate bash completion for command', allowed: Allowed::TYPES_NONE){@bash_completion = true}
|
|
355
|
+
@context.options.declare(:show_config, 'Display parameters used for the provided action', allowed: Allowed::TYPES_NONE){@option_show_config = true}
|
|
356
|
+
@context.options.declare(:version, 'Display version', allowed: Allowed::TYPES_NONE, short: 'v'){@context.formatter.display_message(:data, Cli::VERSION); Process.exit(0)} # rubocop:disable Style/Semicolon
|
|
356
357
|
@context.options.declare(
|
|
357
358
|
:ui, 'Method to start browser',
|
|
358
|
-
|
|
359
|
+
allowed: USER_INTERFACES,
|
|
359
360
|
handler: {o: Environment.instance, m: :url_method}
|
|
360
361
|
)
|
|
361
362
|
@context.options.declare(
|
|
362
363
|
:invalid_characters, 'Replacement character and invalid filename characters',
|
|
363
364
|
handler: {o: Environment.instance, m: :file_illegal_characters}
|
|
364
365
|
)
|
|
365
|
-
@context.options.declare(:log_level, 'Log level',
|
|
366
|
-
@context.options.declare(:log_format, 'Log formatter',
|
|
367
|
-
@context.options.declare(:logger, 'Logging method',
|
|
368
|
-
@context.options.declare(:lock_port, 'Prevent dual execution of a command, e.g. in cron',
|
|
369
|
-
@context.options.declare(:once_only, 'Process only new items (some commands)',
|
|
370
|
-
@context.options.declare(:log_secrets, 'Show passwords in logs',
|
|
371
|
-
@context.options.declare(:clean_temp, 'Cleanup temporary files on exit',
|
|
366
|
+
@context.options.declare(:log_level, 'Log level', allowed: Log::LEVELS, handler: {o: Log.instance, m: :level})
|
|
367
|
+
@context.options.declare(:log_format, 'Log formatter', allowed: [Proc, Logger::Formatter, String], handler: {o: Log.instance, m: :formatter})
|
|
368
|
+
@context.options.declare(:logger, 'Logging method', allowed: Log::LOG_TYPES, handler: {o: Log.instance, m: :logger_type})
|
|
369
|
+
@context.options.declare(:lock_port, 'Prevent dual execution of a command, e.g. in cron', allowed: Allowed::TYPES_INTEGER)
|
|
370
|
+
@context.options.declare(:once_only, 'Process only new items (some commands)', allowed: Allowed::TYPES_BOOLEAN, default: false)
|
|
371
|
+
@context.options.declare(:log_secrets, 'Show passwords in logs', allowed: Allowed::TYPES_BOOLEAN, handler: {o: SecretHider.instance, m: :log_secrets})
|
|
372
|
+
@context.options.declare(:clean_temp, 'Cleanup temporary files on exit', allowed: Allowed::TYPES_BOOLEAN, handler: {o: TempFileManager.instance, m: :cleanup_on_exit})
|
|
372
373
|
@context.options.declare(:temp_folder, 'Temporary folder', handler: {o: TempFileManager.instance, m: :global_temp})
|
|
373
|
-
@context.options.declare(:pid_file, 'Write process identifier to file, delete on exit'
|
|
374
|
+
@context.options.declare(:pid_file, 'Write process identifier to file, delete on exit')
|
|
375
|
+
@context.options.declare(
|
|
376
|
+
:parser, 'Default parser for structured parameters and options',
|
|
377
|
+
handler: {o: ExtendedValue.instance, m: :default_decoder},
|
|
378
|
+
allowed: ExtendedValue::DEFAULT_DECODERS,
|
|
379
|
+
default: ExtendedValue::DEFAULT_DECODERS.first
|
|
380
|
+
)
|
|
374
381
|
# Parse declared options
|
|
375
382
|
@context.options.parse_options!
|
|
376
383
|
end
|