aspera-cli 4.7.0 → 4.9.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 +0 -0
- data/README.md +1267 -999
- data/bin/ascli +20 -1
- data/bin/asession +37 -34
- data/docs/test_env.conf +7 -3
- data/examples/aoc.rb +13 -12
- data/examples/dascli +23 -0
- data/examples/faspex4.rb +34 -29
- data/examples/{transfer.rb → node.rb} +31 -59
- data/examples/server.rb +93 -0
- data/lib/aspera/aoc.rb +153 -143
- data/lib/aspera/ascmd.rb +56 -45
- data/lib/aspera/ats_api.rb +9 -6
- data/lib/aspera/cli/basic_auth_plugin.rb +18 -16
- data/lib/aspera/cli/extended_value.rb +33 -30
- data/lib/aspera/cli/formater.rb +105 -111
- data/lib/aspera/cli/info.rb +3 -2
- 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 +110 -90
- data/lib/aspera/cli/manager.rb +99 -88
- data/lib/aspera/cli/plugin.rb +98 -39
- data/lib/aspera/cli/plugins/alee.rb +6 -5
- data/lib/aspera/cli/plugins/aoc.rb +581 -450
- 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 +488 -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 +206 -172
- data/lib/aspera/cli/plugins/faspex5.rb +109 -74
- data/lib/aspera/cli/plugins/node.rb +379 -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 +50 -150
- data/lib/aspera/cli/plugins/shares.rb +61 -27
- data/lib/aspera/cli/plugins/sync.rb +15 -14
- data/lib/aspera/cli/transfer_agent.rb +75 -64
- 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 +33 -10
- data/lib/aspera/fasp/agent_base.rb +35 -30
- 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 +130 -126
- data/lib/aspera/fasp/listener.rb +1 -0
- data/lib/aspera/fasp/parameters.rb +71 -60
- data/lib/aspera/fasp/parameters.yaml +69 -17
- 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 +23 -13
- data/lib/aspera/id_generator.rb +16 -13
- data/lib/aspera/keychain/encrypted_hash.rb +61 -46
- data/lib/aspera/keychain/macos_security.rb +26 -24
- data/lib/aspera/log.rb +35 -39
- data/lib/aspera/nagios.rb +36 -28
- data/lib/aspera/node.rb +19 -19
- data/lib/aspera/oauth.rb +120 -100
- data/lib/aspera/open_application.rb +25 -22
- data/lib/aspera/persistency_action_once.rb +9 -8
- data/lib/aspera/persistency_folder.rb +13 -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 +27 -23
- data/lib/aspera/rest.rb +73 -74
- data/lib/aspera/rest_call_error.rb +1 -0
- data/lib/aspera/rest_error_analyzer.rb +23 -19
- data/lib/aspera/rest_errors_aspera.rb +43 -40
- data/lib/aspera/secret_hider.rb +74 -0
- data/lib/aspera/ssh.rb +13 -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 +17 -18
- data/lib/aspera/web_auth.rb +17 -15
- data.tar.gz.sig +5 -0
- metadata +119 -35
- metadata.gz.sig +0 -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[text nagios ruby json jsonpp yaml table csv].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,27 @@ 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
|
150
|
+
when :text
|
151
|
+
display_message(:data,res_data.to_s)
|
156
152
|
when :nagios
|
157
153
|
Nagios.process(res_data)
|
158
154
|
when :ruby
|
159
|
-
display_message(:data,PP.pp(res_data
|
155
|
+
display_message(:data,PP.pp(res_data,+''))
|
160
156
|
when :json
|
161
157
|
display_message(:data,JSON.generate(res_data))
|
162
158
|
when :jsonpp
|
@@ -165,52 +161,50 @@ module Aspera
|
|
165
161
|
display_message(:data,res_data.to_yaml)
|
166
162
|
when :table,:csv
|
167
163
|
if !@option_transpose_single && results[:type].eql?(:single_object)
|
168
|
-
results[:type]
|
169
|
-
res_data=[res_data]
|
164
|
+
results[:type] = :object_list
|
165
|
+
res_data = [res_data]
|
170
166
|
end
|
171
167
|
case results[:type]
|
172
168
|
when :object_list # goes to table display
|
173
169
|
raise "internal error: unexpected type: #{res_data.class}, expecting Array" unless res_data.is_a?(Array)
|
174
170
|
# :object_list is an array of hash tables, where key=colum name
|
175
171
|
table_rows_hash_val = res_data
|
176
|
-
final_table_columns=nil
|
172
|
+
final_table_columns = nil
|
177
173
|
if @option_flat_hash
|
178
|
-
table_rows_hash_val.
|
179
|
-
self.class.flatten_object(obj,results[:option_expand_last])
|
180
|
-
end
|
174
|
+
table_rows_hash_val.map!{|obj|self.class.flattened_object(obj,expand_last: results[:option_expand_last])}
|
181
175
|
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)}
|
176
|
+
final_table_columns =
|
177
|
+
case user_asked_fields_list_str
|
178
|
+
when FIELDS_DEFAULT then result_default_fields(results,table_rows_hash_val)
|
179
|
+
when FIELDS_ALL then result_all_fields(results,table_rows_hash_val)
|
191
180
|
else
|
192
|
-
user_asked_fields_list_str.
|
181
|
+
if user_asked_fields_list_str.start_with?('+')
|
182
|
+
result_default_fields(results,table_rows_hash_val).push(*user_asked_fields_list_str.gsub(/^\+/,'').split(','))
|
183
|
+
elsif user_asked_fields_list_str.start_with?('-')
|
184
|
+
result_default_fields(results,table_rows_hash_val).reject{|i| user_asked_fields_list_str.gsub(/^-/,'').split(',').include?(i)}
|
185
|
+
else
|
186
|
+
user_asked_fields_list_str.split(',')
|
187
|
+
end
|
193
188
|
end
|
194
|
-
end
|
195
189
|
when :single_object # goes to table display
|
196
190
|
# :single_object is a simple hash table (can be nested)
|
197
191
|
raise "internal error: expecting Hash: got #{res_data.class}: #{res_data}" unless res_data.is_a?(Hash)
|
198
|
-
final_table_columns = results[:columns] || [
|
192
|
+
final_table_columns = results[:columns] || %w[key value]
|
199
193
|
if @option_flat_hash
|
200
|
-
self.class.
|
194
|
+
res_data=self.class.flattened_object(res_data,expand_last: results[:option_expand_last])
|
201
195
|
self.class.flatten_name_value_list(res_data)
|
202
196
|
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] } }
|
197
|
+
asked_fields =
|
198
|
+
case user_asked_fields_list_str
|
199
|
+
when FIELDS_DEFAULT then results[:fields] || res_data.keys
|
200
|
+
when FIELDS_ALL then res_data.keys
|
201
|
+
else user_asked_fields_list_str.split(',')
|
202
|
+
end
|
203
|
+
table_rows_hash_val = asked_fields.map { |i| { final_table_columns.first => i, final_table_columns.last => res_data[i] } }
|
210
204
|
when :value_list # goes to table display
|
211
205
|
# :value_list is a simple array of values, name of column provided in the :name
|
212
206
|
final_table_columns = [results[:name]]
|
213
|
-
table_rows_hash_val=res_data.map { |i| { results[:name] => i } }
|
207
|
+
table_rows_hash_val = res_data.map { |i| { results[:name] => i } }
|
214
208
|
when :empty # no table
|
215
209
|
display_message(:info,'empty')
|
216
210
|
return
|
@@ -227,7 +221,7 @@ module Aspera
|
|
227
221
|
return
|
228
222
|
when :other_struct # no table
|
229
223
|
# :other_struct is any other type of structure
|
230
|
-
display_message(:data,PP.pp(res_data
|
224
|
+
display_message(:data,PP.pp(res_data,+''))
|
231
225
|
return
|
232
226
|
else
|
233
227
|
raise "unknown data type: #{results[:type]}"
|
@@ -239,18 +233,18 @@ module Aspera
|
|
239
233
|
return
|
240
234
|
end
|
241
235
|
# 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?(
|
236
|
+
table_rows_hash_val = results[:textify].call(table_rows_hash_val) if results.has_key?(:textify)
|
237
|
+
unless @option_select.nil? || (@option_select.respond_to?(:empty?) && @option_select.empty?)
|
244
238
|
raise CliBadArgument,"expecting hash for select, have #{@option_select.class}: #{@option_select}" unless @option_select.is_a?(Hash)
|
245
239
|
@option_select.each{|k,v|table_rows_hash_val.select!{|i|i[k].eql?(v)}}
|
246
240
|
end
|
247
241
|
# 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 } }
|
242
|
+
final_table_rows = table_rows_hash_val.map { |r| final_table_columns.map { |c| r[c].to_s } }
|
249
243
|
# here : final_table_columns : list of column names
|
250
244
|
# here: final_table_rows : array of list of value
|
251
245
|
case @option_format
|
252
246
|
when :table
|
253
|
-
style
|
247
|
+
style = @option_table_style.chars
|
254
248
|
# display the table !
|
255
249
|
#display_message(:data,Text::Table.new(
|
256
250
|
#head: final_table_columns,
|
@@ -259,11 +253,11 @@ module Aspera
|
|
259
253
|
#vertical_boundary: style[1],
|
260
254
|
#boundary_intersection: style[2]))
|
261
255
|
display_message(:data,Terminal::Table.new(
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
256
|
+
headings: final_table_columns,
|
257
|
+
rows: final_table_rows,
|
258
|
+
border_x: style[0],
|
259
|
+
border_y: style[1],
|
260
|
+
border_i: style[2]))
|
267
261
|
when :csv
|
268
262
|
display_message(:data,final_table_rows.map{|t| t.join(CSV_FIELD_SEPARATOR)}.join(CSV_RECORD_SEPARATOR))
|
269
263
|
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
|
@@ -10,8 +11,8 @@ module Aspera
|
|
10
11
|
SRC_URL = 'https://github.com/IBM/aspera-cli'
|
11
12
|
# set this to warn in advance when minimum required ruby version will increase
|
12
13
|
# for example currently minimum version is 2.4 in gemspec, but future minimum will be 2.5
|
13
|
-
# set to
|
14
|
+
# set to current 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
|