aspera-cli 4.7.0 → 4.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +1 -0
- data/README.md +844 -861
- data/bin/ascli +20 -1
- data/bin/asession +37 -34
- data/docs/test_env.conf +11 -3
- data/examples/aoc.rb +13 -12
- data/examples/dascli +26 -0
- data/examples/faspex4.rb +34 -29
- data/examples/transfer.rb +30 -29
- data/lib/aspera/aoc.rb +151 -143
- data/lib/aspera/ascmd.rb +56 -45
- data/lib/aspera/ats_api.rb +6 -5
- data/lib/aspera/cli/basic_auth_plugin.rb +18 -16
- data/lib/aspera/cli/extended_value.rb +32 -30
- data/lib/aspera/cli/formater.rb +103 -111
- data/lib/aspera/cli/info.rb +2 -1
- data/lib/aspera/cli/listener/line_dump.rb +1 -0
- data/lib/aspera/cli/listener/logger.rb +1 -0
- data/lib/aspera/cli/listener/progress.rb +13 -12
- data/lib/aspera/cli/listener/progress_multi.rb +21 -20
- data/lib/aspera/cli/main.rb +106 -89
- data/lib/aspera/cli/manager.rb +96 -85
- data/lib/aspera/cli/plugin.rb +50 -32
- data/lib/aspera/cli/plugins/alee.rb +6 -5
- data/lib/aspera/cli/plugins/aoc.rb +521 -426
- data/lib/aspera/cli/plugins/ats.rb +84 -83
- data/lib/aspera/cli/plugins/bss.rb +30 -27
- data/lib/aspera/cli/plugins/config.rb +483 -397
- data/lib/aspera/cli/plugins/console.rb +17 -15
- data/lib/aspera/cli/plugins/cos.rb +26 -35
- data/lib/aspera/cli/plugins/faspex.rb +201 -168
- data/lib/aspera/cli/plugins/faspex5.rb +109 -74
- data/lib/aspera/cli/plugins/node.rb +378 -189
- data/lib/aspera/cli/plugins/orchestrator.rb +71 -65
- data/lib/aspera/cli/plugins/preview.rb +131 -122
- data/lib/aspera/cli/plugins/server.rb +94 -93
- data/lib/aspera/cli/plugins/shares.rb +42 -28
- data/lib/aspera/cli/plugins/sync.rb +15 -14
- data/lib/aspera/cli/transfer_agent.rb +56 -52
- data/lib/aspera/cli/version.rb +2 -1
- data/lib/aspera/colors.rb +29 -28
- data/lib/aspera/command_line_builder.rb +50 -43
- data/lib/aspera/cos_node.rb +64 -38
- data/lib/aspera/data_repository.rb +1 -0
- data/lib/aspera/environment.rb +18 -8
- data/lib/aspera/fasp/agent_base.rb +26 -23
- data/lib/aspera/fasp/agent_connect.rb +35 -30
- data/lib/aspera/fasp/agent_direct.rb +68 -60
- data/lib/aspera/fasp/agent_httpgw.rb +71 -64
- data/lib/aspera/fasp/agent_node.rb +24 -23
- data/lib/aspera/fasp/agent_trsdk.rb +19 -20
- data/lib/aspera/fasp/error.rb +2 -1
- data/lib/aspera/fasp/error_info.rb +79 -68
- data/lib/aspera/fasp/installation.rb +122 -114
- data/lib/aspera/fasp/listener.rb +1 -0
- data/lib/aspera/fasp/parameters.rb +44 -41
- data/lib/aspera/fasp/resume_policy.rb +14 -11
- data/lib/aspera/fasp/transfer_spec.rb +6 -5
- data/lib/aspera/fasp/uri.rb +25 -24
- data/lib/aspera/faspex_gw.rb +83 -72
- data/lib/aspera/hash_ext.rb +10 -12
- data/lib/aspera/id_generator.rb +8 -7
- data/lib/aspera/keychain/encrypted_hash.rb +60 -45
- data/lib/aspera/keychain/macos_security.rb +26 -24
- data/lib/aspera/log.rb +34 -38
- data/lib/aspera/nagios.rb +14 -13
- data/lib/aspera/node.rb +19 -19
- data/lib/aspera/oauth.rb +121 -101
- data/lib/aspera/open_application.rb +6 -5
- data/lib/aspera/persistency_action_once.rb +9 -8
- data/lib/aspera/persistency_folder.rb +10 -9
- data/lib/aspera/preview/file_types.rb +261 -266
- data/lib/aspera/preview/generator.rb +74 -73
- data/lib/aspera/preview/image_error.png +0 -0
- data/lib/aspera/preview/options.rb +7 -6
- data/lib/aspera/preview/utils.rb +30 -33
- data/lib/aspera/preview/video_error.png +0 -0
- data/lib/aspera/proxy_auto_config.rb +25 -23
- data/lib/aspera/rest.rb +73 -74
- data/lib/aspera/rest_call_error.rb +1 -0
- data/lib/aspera/rest_error_analyzer.rb +11 -9
- data/lib/aspera/rest_errors_aspera.rb +5 -4
- data/lib/aspera/secret_hider.rb +68 -0
- data/lib/aspera/ssh.rb +12 -10
- data/lib/aspera/sync.rb +49 -47
- data/lib/aspera/temp_file_manager.rb +7 -5
- data/lib/aspera/timer_limiter.rb +9 -8
- data/lib/aspera/uri_reader.rb +11 -14
- data/lib/aspera/web_auth.rb +17 -15
- data.tar.gz.sig +0 -0
- metadata +117 -34
- metadata.gz.sig +2 -0
- data/bin/dascli +0 -13
data/lib/aspera/cli/formater.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'aspera/secret_hider'
|
2
4
|
require 'terminal-table'
|
3
5
|
require 'yaml'
|
4
6
|
require 'pp'
|
@@ -7,75 +9,78 @@ module Aspera
|
|
7
9
|
module Cli
|
8
10
|
# Take care of output
|
9
11
|
class Formater
|
10
|
-
FIELDS_ALL='ALL'
|
11
|
-
FIELDS_DEFAULT='DEF'
|
12
|
+
FIELDS_ALL = 'ALL'
|
13
|
+
FIELDS_DEFAULT = 'DEF'
|
14
|
+
CSV_RECORD_SEPARATOR = "\n"
|
15
|
+
CSV_FIELD_SEPARATOR = ','
|
12
16
|
# supported output formats
|
13
|
-
DISPLAY_FORMATS
|
17
|
+
DISPLAY_FORMATS = %i[table ruby json jsonpp yaml csv nagios].freeze
|
14
18
|
# user output levels
|
15
|
-
DISPLAY_LEVELS=[
|
16
|
-
|
17
|
-
CSV_FIELD_SEPARATOR=','
|
18
|
-
HIDDEN_PASSWORD='🔑'
|
19
|
-
SECRET_KEYWORDS=%w[password secret private_key]
|
19
|
+
DISPLAY_LEVELS = %i[info data error].freeze
|
20
|
+
CONF_OVERVIEW_KEYS=%w[config parameter value].freeze
|
20
21
|
|
21
|
-
private_constant :FIELDS_ALL,:FIELDS_DEFAULT,:DISPLAY_FORMATS,:DISPLAY_LEVELS,:CSV_RECORD_SEPARATOR,:CSV_FIELD_SEPARATOR
|
22
|
+
private_constant :FIELDS_ALL,:FIELDS_DEFAULT,:DISPLAY_FORMATS,:DISPLAY_LEVELS,:CSV_RECORD_SEPARATOR,:CSV_FIELD_SEPARATOR,
|
23
|
+
:CONF_OVERVIEW_KEYS
|
22
24
|
|
23
|
-
class<<self
|
24
|
-
#
|
25
|
-
#
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
class << self
|
26
|
+
# special for Aspera on Cloud display node
|
27
|
+
# {"param" => [{"name"=>"foo","value"=>"bar"}]} will be expanded to {"param.foo" : "bar"}
|
28
|
+
def flatten_name_value_list(hash)
|
29
|
+
hash.keys.each do |k|
|
30
|
+
v = hash[k]
|
31
|
+
next unless v.is_a?(Array) && v.map(&:class).uniq.eql?([Hash]) && v.map(&:keys).flatten.sort.uniq.eql?(%w[name value])
|
32
|
+
v.each do |pair|
|
33
|
+
hash["#{k}.#{pair['name']}"] = pair['value']
|
34
|
+
end
|
35
|
+
hash.delete(k)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def flatten_config_overview(conffile)
|
40
|
+
r = []
|
41
|
+
conffile.each do |config,preset|
|
42
|
+
preset.each do |parameter,value|
|
43
|
+
r.push(CONF_OVERVIEW_KEYS.zip([config,parameter,value]).to_h)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
return r
|
47
|
+
end
|
48
|
+
|
49
|
+
def simple_hash?(h)
|
50
|
+
!(h.values.any?{|v|[Hash,Array].any?{|c|v.is_a?(c)}})
|
31
51
|
end
|
32
52
|
|
33
53
|
# recursive function to modify a hash
|
34
54
|
# @param source [Hash] to be modified
|
35
|
-
# @param
|
55
|
+
# @param expand_last [bool] truer if last level is not
|
56
|
+
# @param result [Hash] new hash flattened
|
36
57
|
# @param prefix [String] true if last level is not
|
37
|
-
|
38
|
-
|
39
|
-
#is_simple_hash=source.is_a?(Hash) and source.values.inject(true){|m,v| xxx=!v.respond_to?(:each) and m;puts("->#{xxx}>#{v.respond_to?(:each)} #{v}-");xxx}
|
40
|
-
is_simple_hash=false
|
41
|
-
Log.log.debug("(#{keep_last})[#{is_simple_hash}] -#{source.values}- \n-#{source}-")
|
42
|
-
return source if keep_last && is_simple_hash
|
58
|
+
def flattened_object(source,result: {},prefix: '',expand_last: false)
|
59
|
+
Log.log.debug("(#{expand_last})[#{simple_hash?(source)}] -#{source.values}- \n-#{source}-")
|
43
60
|
source.each do |k,v|
|
44
|
-
if v.is_a?(Hash) && (
|
45
|
-
|
61
|
+
if v.is_a?(Hash) && !(expand_last && simple_hash?(v))
|
62
|
+
flattened_object(v,result: result,prefix: prefix + k.to_s + '.',expand_last: expand_last)
|
46
63
|
else
|
47
|
-
|
64
|
+
result[prefix + k.to_s] = v
|
48
65
|
end
|
49
66
|
end
|
50
|
-
return
|
51
|
-
end
|
52
|
-
|
53
|
-
# special for Aspera on Cloud display node
|
54
|
-
# {"param" => [{"name"=>"foo","value"=>"bar"}]} will be expanded to {"param.foo" : "bar"}
|
55
|
-
def flatten_name_value_list(hash)
|
56
|
-
hash.keys.each do |k|
|
57
|
-
v=hash[k]
|
58
|
-
next unless v.is_a?(Array) && v.map(&:class).uniq.eql?([Hash]) && v.map(&:keys).flatten.sort.uniq.eql?(['name', 'value'])
|
59
|
-
v.each do |pair|
|
60
|
-
hash["#{k}.#{pair['name']}"]=pair['value']
|
61
|
-
end
|
62
|
-
hash.delete(k)
|
63
|
-
end
|
67
|
+
return result
|
64
68
|
end
|
65
69
|
end
|
66
70
|
|
67
|
-
attr_accessor :option_flat_hash,:option_transpose_single,:option_format,:option_display,:option_fields,:option_table_style
|
71
|
+
attr_accessor :option_flat_hash,:option_transpose_single,:option_format,:option_display,:option_fields,:option_table_style,
|
72
|
+
:option_select,:option_show_secrets
|
68
73
|
|
69
74
|
# adds options but does not parse
|
70
75
|
def initialize(opt_mgr)
|
71
|
-
@option_format
|
72
|
-
@option_display
|
73
|
-
@option_fields=FIELDS_DEFAULT
|
74
|
-
@option_select=nil
|
75
|
-
@option_table_style=':.:'
|
76
|
-
@option_flat_hash=true
|
77
|
-
@option_transpose_single=true
|
78
|
-
@option_show_secrets=
|
76
|
+
@option_format = :table
|
77
|
+
@option_display = :info
|
78
|
+
@option_fields = FIELDS_DEFAULT
|
79
|
+
@option_select = nil
|
80
|
+
@option_table_style = ':.:'
|
81
|
+
@option_flat_hash = true
|
82
|
+
@option_transpose_single = true
|
83
|
+
@option_show_secrets = false
|
79
84
|
opt_mgr.set_obj_attr(:format,self,:option_format)
|
80
85
|
opt_mgr.set_obj_attr(:display,self,:option_display)
|
81
86
|
opt_mgr.set_obj_attr(:fields,self,:option_fields)
|
@@ -95,10 +100,13 @@ module Aspera
|
|
95
100
|
end
|
96
101
|
|
97
102
|
# main output method
|
103
|
+
# data: for requested data, not displayed if level==error
|
104
|
+
# info: additional info, displayed if level==info
|
105
|
+
# error: always displayed on stderr
|
98
106
|
def display_message(message_level,message)
|
99
107
|
case message_level
|
100
|
-
when :info then $stdout.puts(message) if @option_display.eql?(:info)
|
101
108
|
when :data then $stdout.puts(message) unless @option_display.eql?(:error)
|
109
|
+
when :info then $stdout.puts(message) if @option_display.eql?(:info)
|
102
110
|
when :error then $stderr.puts(message)
|
103
111
|
else raise "wrong message_level:#{message_level}"
|
104
112
|
end
|
@@ -112,7 +120,7 @@ module Aspera
|
|
112
120
|
unless results[:fields].nil?
|
113
121
|
raise "internal error: [fields] must be Array, not #{results[:fields].class}" unless results[:fields].is_a?(Array)
|
114
122
|
if results[:fields].first.eql?(:all_but) && !table_rows_hash_val.empty?
|
115
|
-
filter=results[:fields][1..-1]
|
123
|
+
filter = results[:fields][1..-1]
|
116
124
|
return table_rows_hash_val.first.keys.reject{|i|filter.include?(i)}
|
117
125
|
end
|
118
126
|
return results[:fields]
|
@@ -124,39 +132,25 @@ module Aspera
|
|
124
132
|
def result_all_fields(_results,table_rows_hash_val)
|
125
133
|
raise 'internal error: must be array' unless table_rows_hash_val.is_a?(Array)
|
126
134
|
# get the list of all column names used in all lines, not just frst one, as all lines may have different columns
|
127
|
-
return table_rows_hash_val.each_with_object({}){|v,m|v.keys.each{|c|m[c]=true};}.keys
|
128
|
-
end
|
129
|
-
|
130
|
-
def deep_remove_secret(obj)
|
131
|
-
return if @option_show_secrets
|
132
|
-
case obj
|
133
|
-
when Array then obj.each{|i|deep_remove_secret(i)}
|
134
|
-
when Hash
|
135
|
-
obj.keys.each do |k|
|
136
|
-
next if %w[show_secrets log_secrets].any?{|kw|kw.eql?(k)}
|
137
|
-
if k.is_a?(String) && SECRET_KEYWORDS.any?{|kw|k.include?(kw)}
|
138
|
-
obj[k]=HIDDEN_PASSWORD
|
139
|
-
elsif obj[k].is_a?(Hash)
|
140
|
-
deep_remove_secret(obj[k])
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
135
|
+
return table_rows_hash_val.each_with_object({}){|v,m|v.keys.each{|c|m[c] = true};}.keys
|
144
136
|
end
|
145
137
|
|
146
138
|
# this method displays the results, especially the table format
|
147
139
|
def display_results(results)
|
148
140
|
raise "INTERNAL ERROR, result must be Hash (got: #{results.class}: #{results})" unless results.is_a?(Hash)
|
149
141
|
raise 'INTERNAL ERROR, result must have type' unless results.has_key?(:type)
|
150
|
-
raise 'INTERNAL ERROR, result must have data' unless results.has_key?(:data) || [
|
151
|
-
res_data=results[:data]
|
152
|
-
|
142
|
+
raise 'INTERNAL ERROR, result must have data' unless results.has_key?(:data) || %i[empty nothing].include?(results[:type])
|
143
|
+
res_data = results[:data]
|
144
|
+
# for config overvuew, it is name and value
|
145
|
+
is_config_overview = res_data.is_a?(Array) && !res_data.empty? && res_data.first.is_a?(Hash) && res_data.first.keys.sort.eql?(CONF_OVERVIEW_KEYS)
|
146
|
+
SecretHider.deep_remove_secret(res_data, is_name_value: is_config_overview) unless @option_show_secrets || @option_display.eql?(:data)
|
153
147
|
# comma separated list in string format
|
154
|
-
user_asked_fields_list_str
|
148
|
+
user_asked_fields_list_str = @option_fields
|
155
149
|
case @option_format
|
156
150
|
when :nagios
|
157
151
|
Nagios.process(res_data)
|
158
152
|
when :ruby
|
159
|
-
display_message(:data,PP.pp(res_data
|
153
|
+
display_message(:data,PP.pp(res_data,+''))
|
160
154
|
when :json
|
161
155
|
display_message(:data,JSON.generate(res_data))
|
162
156
|
when :jsonpp
|
@@ -165,52 +159,50 @@ module Aspera
|
|
165
159
|
display_message(:data,res_data.to_yaml)
|
166
160
|
when :table,:csv
|
167
161
|
if !@option_transpose_single && results[:type].eql?(:single_object)
|
168
|
-
results[:type]
|
169
|
-
res_data=[res_data]
|
162
|
+
results[:type] = :object_list
|
163
|
+
res_data = [res_data]
|
170
164
|
end
|
171
165
|
case results[:type]
|
172
166
|
when :object_list # goes to table display
|
173
167
|
raise "internal error: unexpected type: #{res_data.class}, expecting Array" unless res_data.is_a?(Array)
|
174
168
|
# :object_list is an array of hash tables, where key=colum name
|
175
169
|
table_rows_hash_val = res_data
|
176
|
-
final_table_columns=nil
|
170
|
+
final_table_columns = nil
|
177
171
|
if @option_flat_hash
|
178
|
-
table_rows_hash_val.
|
179
|
-
self.class.flatten_object(obj,results[:option_expand_last])
|
180
|
-
end
|
172
|
+
table_rows_hash_val.map!{|obj|self.class.flattened_object(obj,expand_last: results[:option_expand_last])}
|
181
173
|
end
|
182
|
-
final_table_columns=
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
else
|
187
|
-
if user_asked_fields_list_str.start_with?('+')
|
188
|
-
result_default_fields(results,table_rows_hash_val).push(*user_asked_fields_list_str.gsub(/^\+/,'').split(','))
|
189
|
-
elsif user_asked_fields_list_str.start_with?('-')
|
190
|
-
result_default_fields(results,table_rows_hash_val).reject{|i| user_asked_fields_list_str.gsub(/^-/,'').split(',').include?(i)}
|
174
|
+
final_table_columns =
|
175
|
+
case user_asked_fields_list_str
|
176
|
+
when FIELDS_DEFAULT then result_default_fields(results,table_rows_hash_val)
|
177
|
+
when FIELDS_ALL then result_all_fields(results,table_rows_hash_val)
|
191
178
|
else
|
192
|
-
user_asked_fields_list_str.
|
179
|
+
if user_asked_fields_list_str.start_with?('+')
|
180
|
+
result_default_fields(results,table_rows_hash_val).push(*user_asked_fields_list_str.gsub(/^\+/,'').split(','))
|
181
|
+
elsif user_asked_fields_list_str.start_with?('-')
|
182
|
+
result_default_fields(results,table_rows_hash_val).reject{|i| user_asked_fields_list_str.gsub(/^-/,'').split(',').include?(i)}
|
183
|
+
else
|
184
|
+
user_asked_fields_list_str.split(',')
|
185
|
+
end
|
193
186
|
end
|
194
|
-
end
|
195
187
|
when :single_object # goes to table display
|
196
188
|
# :single_object is a simple hash table (can be nested)
|
197
189
|
raise "internal error: expecting Hash: got #{res_data.class}: #{res_data}" unless res_data.is_a?(Hash)
|
198
|
-
final_table_columns = results[:columns] || [
|
190
|
+
final_table_columns = results[:columns] || %w[key value]
|
199
191
|
if @option_flat_hash
|
200
|
-
self.class.
|
192
|
+
res_data=self.class.flattened_object(res_data,expand_last: results[:option_expand_last])
|
201
193
|
self.class.flatten_name_value_list(res_data)
|
202
194
|
end
|
203
|
-
asked_fields=
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
table_rows_hash_val=asked_fields.map { |i| { final_table_columns.first => i, final_table_columns.last => res_data[i] } }
|
195
|
+
asked_fields =
|
196
|
+
case user_asked_fields_list_str
|
197
|
+
when FIELDS_DEFAULT then results[:fields] || res_data.keys
|
198
|
+
when FIELDS_ALL then res_data.keys
|
199
|
+
else user_asked_fields_list_str.split(',')
|
200
|
+
end
|
201
|
+
table_rows_hash_val = asked_fields.map { |i| { final_table_columns.first => i, final_table_columns.last => res_data[i] } }
|
210
202
|
when :value_list # goes to table display
|
211
203
|
# :value_list is a simple array of values, name of column provided in the :name
|
212
204
|
final_table_columns = [results[:name]]
|
213
|
-
table_rows_hash_val=res_data.map { |i| { results[:name] => i } }
|
205
|
+
table_rows_hash_val = res_data.map { |i| { results[:name] => i } }
|
214
206
|
when :empty # no table
|
215
207
|
display_message(:info,'empty')
|
216
208
|
return
|
@@ -227,7 +219,7 @@ module Aspera
|
|
227
219
|
return
|
228
220
|
when :other_struct # no table
|
229
221
|
# :other_struct is any other type of structure
|
230
|
-
display_message(:data,PP.pp(res_data
|
222
|
+
display_message(:data,PP.pp(res_data,+''))
|
231
223
|
return
|
232
224
|
else
|
233
225
|
raise "unknown data type: #{results[:type]}"
|
@@ -239,18 +231,18 @@ module Aspera
|
|
239
231
|
return
|
240
232
|
end
|
241
233
|
# convert to string with special function. here table_rows_hash_val is an array of hash
|
242
|
-
table_rows_hash_val=results[:textify].call(table_rows_hash_val) if results.has_key?(:textify)
|
243
|
-
unless @option_select.nil? || (@option_select.respond_to?(
|
234
|
+
table_rows_hash_val = results[:textify].call(table_rows_hash_val) if results.has_key?(:textify)
|
235
|
+
unless @option_select.nil? || (@option_select.respond_to?(:empty?) && @option_select.empty?)
|
244
236
|
raise CliBadArgument,"expecting hash for select, have #{@option_select.class}: #{@option_select}" unless @option_select.is_a?(Hash)
|
245
237
|
@option_select.each{|k,v|table_rows_hash_val.select!{|i|i[k].eql?(v)}}
|
246
238
|
end
|
247
239
|
# convert data to string, and keep only display fields
|
248
|
-
final_table_rows=table_rows_hash_val.map { |r| final_table_columns.map { |c| r[c].to_s } }
|
240
|
+
final_table_rows = table_rows_hash_val.map { |r| final_table_columns.map { |c| r[c].to_s } }
|
249
241
|
# here : final_table_columns : list of column names
|
250
242
|
# here: final_table_rows : array of list of value
|
251
243
|
case @option_format
|
252
244
|
when :table
|
253
|
-
style
|
245
|
+
style = @option_table_style.chars
|
254
246
|
# display the table !
|
255
247
|
#display_message(:data,Text::Table.new(
|
256
248
|
#head: final_table_columns,
|
@@ -259,11 +251,11 @@ module Aspera
|
|
259
251
|
#vertical_boundary: style[1],
|
260
252
|
#boundary_intersection: style[2]))
|
261
253
|
display_message(:data,Terminal::Table.new(
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
254
|
+
headings: final_table_columns,
|
255
|
+
rows: final_table_rows,
|
256
|
+
border_x: style[0],
|
257
|
+
border_y: style[1],
|
258
|
+
border_i: style[2]))
|
267
259
|
when :csv
|
268
260
|
display_message(:data,final_table_rows.map{|t| t.join(CSV_FIELD_SEPARATOR)}.join(CSV_RECORD_SEPARATOR))
|
269
261
|
end
|
data/lib/aspera/cli/info.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aspera
|
3
4
|
module Cli
|
4
5
|
# name of command line tool, also used as foldername where config is stored
|
@@ -12,6 +13,6 @@ module Aspera
|
|
12
13
|
# for example currently minimum version is 2.4 in gemspec, but future minimum will be 2.5
|
13
14
|
# set to currenmt minimum if there is no deprecation
|
14
15
|
# the actual current minimum required version is in gemspec at required_ruby_version
|
15
|
-
RUBY_FUTURE_MINIMUM_VERSION='2.5'
|
16
|
+
RUBY_FUTURE_MINIMUM_VERSION = '2.5'
|
16
17
|
end
|
17
18
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'aspera/fasp/listener'
|
3
4
|
require 'ruby-progressbar'
|
4
5
|
|
@@ -9,38 +10,38 @@ module Aspera
|
|
9
10
|
class Progress < Fasp::Listener
|
10
11
|
def initialize
|
11
12
|
super
|
12
|
-
@progress=nil
|
13
|
-
@cumulative=0
|
13
|
+
@progress = nil
|
14
|
+
@cumulative = 0
|
14
15
|
end
|
15
16
|
|
16
|
-
BYTE_PER_MEGABIT=(1024*1024)/8
|
17
|
+
BYTE_PER_MEGABIT = (1024 * 1024) / 8
|
17
18
|
|
18
19
|
def event_struct(data)
|
19
20
|
case data['Type']
|
20
21
|
when 'NOTIFICATION'
|
21
22
|
if data.has_key?('PreTransferBytes')
|
22
|
-
@progress=ProgressBar.create(
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
@progress = ProgressBar.create(
|
24
|
+
format: '%a %B %p%% %r Mbps %e',
|
25
|
+
rate_scale: lambda{|rate|rate / BYTE_PER_MEGABIT},
|
26
|
+
title: 'progress',
|
27
|
+
total: data['PreTransferBytes'].to_i)
|
27
28
|
end
|
28
29
|
when 'STOP'
|
29
30
|
# stop event when one file is completed
|
30
|
-
@cumulative+=data['Size'].to_i
|
31
|
+
@cumulative += data['Size'].to_i
|
31
32
|
when 'STATS'
|
32
33
|
if @progress.nil?
|
33
34
|
puts '.'
|
34
35
|
else
|
35
|
-
@progress.progress=data.has_key?('Bytescont') ? @cumulative+data['Bytescont'].to_i : data['TransferBytes'].to_i
|
36
|
+
@progress.progress = data.has_key?('Bytescont') ? @cumulative + data['Bytescont'].to_i : data['TransferBytes'].to_i
|
36
37
|
end
|
37
38
|
when 'DONE'
|
38
39
|
if @progress.nil?
|
39
40
|
# terminate progress by going to next line
|
40
41
|
puts "\n"
|
41
42
|
else
|
42
|
-
@progress.progress
|
43
|
-
@progress=nil
|
43
|
+
@progress.progress = @progress.total
|
44
|
+
@progress = nil
|
44
45
|
end
|
45
46
|
end
|
46
47
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'aspera/fasp/listener'
|
3
4
|
require 'aspera/fasp/agent_base'
|
4
5
|
require 'ruby-progressbar'
|
@@ -10,20 +11,20 @@ module Aspera
|
|
10
11
|
class ProgressMulti < Fasp::Listener
|
11
12
|
def initialize
|
12
13
|
super
|
13
|
-
@progress_bar=nil
|
14
|
-
@sessions={}
|
14
|
+
@progress_bar = nil
|
15
|
+
@sessions = {}
|
15
16
|
end
|
16
17
|
|
17
18
|
def reset
|
18
|
-
@progress_bar=nil
|
19
|
-
@sessions={}
|
19
|
+
@progress_bar = nil
|
20
|
+
@sessions = {}
|
20
21
|
end
|
21
22
|
|
22
|
-
BYTE_PER_MEGABIT=1024*1024/8
|
23
|
+
BYTE_PER_MEGABIT = 1024 * 1024 / 8
|
23
24
|
|
24
25
|
def update_total
|
25
26
|
begin
|
26
|
-
@progress_bar.total
|
27
|
+
@progress_bar.total = @sessions.values.inject(0){|m,s|m += s[:job_size].to_i;m;}
|
27
28
|
rescue StandardError
|
28
29
|
nil
|
29
30
|
end
|
@@ -31,7 +32,7 @@ module Aspera
|
|
31
32
|
|
32
33
|
def update_progress
|
33
34
|
begin
|
34
|
-
@progress_bar.progress
|
35
|
+
@progress_bar.progress = @sessions.values.inject(0){|m,s|m += s[:current].to_i;m;}
|
35
36
|
rescue StandardError
|
36
37
|
nil
|
37
38
|
end
|
@@ -39,41 +40,41 @@ module Aspera
|
|
39
40
|
|
40
41
|
def event_enhanced(data)
|
41
42
|
if @progress_bar.nil?
|
42
|
-
@progress_bar=ProgressBar.create(
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
@progress_bar = ProgressBar.create(
|
44
|
+
format: '%t %a %B %p%% %r Mbps %e',
|
45
|
+
rate_scale: lambda{|rate|rate / BYTE_PER_MEGABIT},
|
46
|
+
title: '',
|
47
|
+
total: nil)
|
47
48
|
end
|
48
49
|
if !data.has_key?(Fasp::AgentBase::LISTENER_SESSION_ID_S)
|
49
50
|
Log.log.error("Internal error: no #{Fasp::AgentBase::LISTENER_SESSION_ID_S} in event: #{data}")
|
50
51
|
return
|
51
52
|
end
|
52
|
-
newtitle
|
53
|
-
@progress_bar.title=newtitle unless @progress_bar.title.eql?(newtitle)
|
54
|
-
session
|
53
|
+
newtitle = @sessions.length < 2 ? '' : "multi=#{@sessions.length}"
|
54
|
+
@progress_bar.title = newtitle unless @progress_bar.title.eql?(newtitle)
|
55
|
+
session = @sessions[data[Fasp::AgentBase::LISTENER_SESSION_ID_S]] ||= {
|
55
56
|
cumulative: 0,
|
56
|
-
job_size:
|
57
|
-
current:
|
57
|
+
job_size: 0,
|
58
|
+
current: 0
|
58
59
|
}
|
59
60
|
case data['type']
|
60
61
|
when 'INIT' # connection to ascp (get id)
|
61
62
|
when 'SESSION' # session information
|
62
63
|
when 'NOTIFICATION' # sent from remote
|
63
64
|
if data.has_key?('pre_transfer_bytes')
|
64
|
-
session[:job_size]=data['pre_transfer_bytes']
|
65
|
+
session[:job_size] = data['pre_transfer_bytes']
|
65
66
|
update_total
|
66
67
|
end
|
67
68
|
when 'STATS' # during transfer
|
68
69
|
if @progress_bar.total.nil?
|
69
70
|
@progress_bar.increment
|
70
71
|
else
|
71
|
-
session[:current]=data.has_key?('bytescont') ? session[:cumulative]+data['bytescont'].to_i : data['transfer_bytes'].to_i
|
72
|
+
session[:current] = data.has_key?('bytescont') ? session[:cumulative] + data['bytescont'].to_i : data['transfer_bytes'].to_i
|
72
73
|
update_progress
|
73
74
|
end
|
74
75
|
when 'STOP'
|
75
76
|
# stop event when one file is completed
|
76
|
-
session[:cumulative]=session[:cumulative]+data['size'].to_i
|
77
|
+
session[:cumulative] = session[:cumulative] + data['size'].to_i
|
77
78
|
when 'DONE' # end of session
|
78
79
|
@sessions.delete(data[Fasp::AgentBase::LISTENER_SESSION_ID_S])
|
79
80
|
update_progress
|