aspera-cli 4.2.1 → 4.2.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
- data/README.md +187 -127
- data/docs/Makefile +4 -4
- data/docs/README.erb.md +206 -38
- data/docs/test_env.conf +2 -1
- data/examples/faspex4.rb +28 -17
- data/lib/aspera/cli/main.rb +47 -19
- data/lib/aspera/cli/plugins/aoc.rb +5 -13
- data/lib/aspera/cli/plugins/config.rb +47 -30
- data/lib/aspera/cli/plugins/faspex.rb +90 -52
- data/lib/aspera/cli/plugins/faspex5.rb +8 -7
- data/lib/aspera/cli/plugins/preview.rb +29 -25
- data/lib/aspera/cli/transfer_agent.rb +71 -44
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/command_line_builder.rb +49 -31
- data/lib/aspera/fasp/parameters.rb +57 -87
- data/lib/aspera/fasp/parameters.yaml +531 -0
- data/lib/aspera/fasp/uri.rb +1 -1
- data/lib/aspera/oauth.rb +4 -4
- data/lib/aspera/sync.rb +40 -35
- metadata +17 -3
- data/docs/transfer_spec.html +0 -99
|
@@ -16,33 +16,47 @@ module Aspera
|
|
|
16
16
|
FILE_LIST_FROM_ARGS='@args'
|
|
17
17
|
# special value for --sources : read file list from transfer spec (--ts)
|
|
18
18
|
FILE_LIST_FROM_TRANSFER_SPEC='@ts'
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
DEFAULT_TRANSFER_NOTIF_TMPL=<<END_OF_TEMPLATE
|
|
20
|
+
From: <%=from_name%> <<%=from_email%>>
|
|
21
|
+
To: <<%=to%>>
|
|
22
|
+
Subject: <%=subject%>
|
|
23
|
+
|
|
24
|
+
Transfer is: <%=global_transfer_status%>
|
|
25
|
+
|
|
26
|
+
<%=ts.to_yaml%>
|
|
27
|
+
END_OF_TEMPLATE
|
|
28
|
+
#%
|
|
29
|
+
private_constant :FILE_LIST_FROM_ARGS,:FILE_LIST_FROM_TRANSFER_SPEC,:DEFAULT_TRANSFER_NOTIF_TMPL
|
|
30
|
+
# @param env external objects: option manager, config file manager
|
|
31
|
+
def initialize(env)
|
|
32
|
+
# same as plugin environment
|
|
33
|
+
@env=env
|
|
34
|
+
# command line can override transfer spec
|
|
35
|
+
@transfer_spec_cmdline={'create_dir'=>true}
|
|
26
36
|
# the currently selected transfer agent
|
|
27
37
|
@agent=nil
|
|
28
38
|
@progress_listener=Listener::ProgressMulti.new
|
|
29
39
|
# source/destination pair, like "paths" of transfer spec
|
|
30
40
|
@transfer_paths=nil
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
options.set_obj_attr(:ts,self,:option_transfer_spec)
|
|
42
|
+
options.add_opt_simple(:ts,"override transfer spec values (Hash, use @json: prefix), current=#{options.get_option(:ts,:optional)}")
|
|
43
|
+
options.add_opt_simple(:local_resume,"set resume policy (Hash, use @json: prefix), current=#{options.get_option(:local_resume,:optional)}")
|
|
44
|
+
options.add_opt_simple(:to_folder,"destination folder for downloaded files")
|
|
45
|
+
options.add_opt_simple(:sources,"list of source files (see doc)")
|
|
46
|
+
options.add_opt_simple(:transfer_info,"additional information for transfer client")
|
|
47
|
+
options.add_opt_list(:src_type,[:list,:pair],"type of file list")
|
|
48
|
+
options.add_opt_list(:transfer,[:direct,:httpgw,:connect,:node,:aoc],"type of transfer")
|
|
49
|
+
options.add_opt_list(:progress,[:none,:native,:multi],"type of progress bar")
|
|
50
|
+
options.set_option(:transfer,:direct)
|
|
51
|
+
options.set_option(:src_type,:list)
|
|
52
|
+
options.set_option(:progress,:native) # use native ascp progress bar as it is more reliable
|
|
53
|
+
options.parse_options!
|
|
44
54
|
end
|
|
45
55
|
|
|
56
|
+
def options; @env[:options];end
|
|
57
|
+
|
|
58
|
+
def config; @env[:config];end
|
|
59
|
+
|
|
46
60
|
def option_transfer_spec; @transfer_spec_cmdline; end
|
|
47
61
|
|
|
48
62
|
# multiple option are merged
|
|
@@ -54,8 +68,8 @@ module Aspera
|
|
|
54
68
|
@agent=instance
|
|
55
69
|
@agent.add_listener(Listener::Logger.new)
|
|
56
70
|
# use local progress bar if asked so, or if native and non local ascp (because only local ascp has native progress bar)
|
|
57
|
-
if
|
|
58
|
-
(
|
|
71
|
+
if options.get_option(:progress,:mandatory).eql?(:multi) or
|
|
72
|
+
(options.get_option(:progress,:mandatory).eql?(:native) and !options.get_option(:transfer,:mandatory).eql?(:direct))
|
|
59
73
|
@agent.add_listener(@progress_listener)
|
|
60
74
|
end
|
|
61
75
|
end
|
|
@@ -63,15 +77,15 @@ module Aspera
|
|
|
63
77
|
# analyze options and create new agent if not already created or set
|
|
64
78
|
def set_agent_by_options
|
|
65
79
|
return nil unless @agent.nil?
|
|
66
|
-
agent_type
|
|
80
|
+
agent_type=options.get_option(:transfer,:mandatory)
|
|
67
81
|
case agent_type
|
|
68
82
|
when :direct
|
|
69
|
-
agent_options
|
|
83
|
+
agent_options=options.get_option(:transfer_info,:optional)
|
|
70
84
|
agent_options=agent_options.symbolize_keys if agent_options.is_a?(Hash)
|
|
71
85
|
new_agent=Fasp::Local.new(agent_options)
|
|
72
|
-
new_agent.quiet=false if
|
|
86
|
+
new_agent.quiet=false if options.get_option(:progress,:mandatory).eql?(:native)
|
|
73
87
|
when :httpgw
|
|
74
|
-
httpgw_config
|
|
88
|
+
httpgw_config=options.get_option(:transfer_info,:mandatory)
|
|
75
89
|
new_agent=Fasp::HttpGW.new(httpgw_config)
|
|
76
90
|
when :connect
|
|
77
91
|
new_agent=Fasp::Connect.new
|
|
@@ -79,12 +93,12 @@ module Aspera
|
|
|
79
93
|
# way for code to setup alternate node api in advance
|
|
80
94
|
# support: @preset:<name>
|
|
81
95
|
# support extended values
|
|
82
|
-
node_config
|
|
96
|
+
node_config=options.get_option(:transfer_info,:optional)
|
|
83
97
|
# if not specified: use default node
|
|
84
98
|
if node_config.nil?
|
|
85
|
-
param_set_name
|
|
99
|
+
param_set_name=config.get_plugin_default_config_name(:node)
|
|
86
100
|
raise CliBadArgument,"No default node configured, Please specify --#{:transfer_info.to_s.gsub('_','-')}" if param_set_name.nil?
|
|
87
|
-
node_config
|
|
101
|
+
node_config=config.preset_by_name(param_set_name)
|
|
88
102
|
end
|
|
89
103
|
Log.log.debug("node=#{node_config}")
|
|
90
104
|
raise CliBadArgument,"the node configuration shall be Hash, not #{node_config.class} (#{node_config}), use either @json:<json> or @preset:<parameter set name>" if !node_config.is_a?(Hash)
|
|
@@ -103,11 +117,11 @@ module Aspera
|
|
|
103
117
|
}})
|
|
104
118
|
new_agent=Fasp::Node.new(node_api)
|
|
105
119
|
when :aoc
|
|
106
|
-
aoc_config
|
|
120
|
+
aoc_config=options.get_option(:transfer_info,:optional)
|
|
107
121
|
if aoc_config.nil?
|
|
108
|
-
param_set_name
|
|
122
|
+
param_set_name=config.get_plugin_default_config_name(:aspera)
|
|
109
123
|
raise CliBadArgument,"No default AoC configured, Please specify --#{:transfer_info.to_s.gsub('_','-')}" if param_set_name.nil?
|
|
110
|
-
aoc_config
|
|
124
|
+
aoc_config=config.preset_by_name(param_set_name)
|
|
111
125
|
end
|
|
112
126
|
Log.log.debug("aoc=#{aoc_config}")
|
|
113
127
|
raise CliBadArgument,"the aoc configuration shall be Hash, not #{aoc_config.class} (#{aoc_config}), refer to manual" if !aoc_config.is_a?(Hash)
|
|
@@ -129,7 +143,7 @@ module Aspera
|
|
|
129
143
|
# sets default if needed
|
|
130
144
|
# param: 'send' or 'receive'
|
|
131
145
|
def destination_folder(direction)
|
|
132
|
-
dest_folder
|
|
146
|
+
dest_folder=options.get_option(:to_folder,:optional)
|
|
133
147
|
return dest_folder unless dest_folder.nil?
|
|
134
148
|
dest_folder=@transfer_spec_cmdline['destination_root']
|
|
135
149
|
return dest_folder unless dest_folder.nil?
|
|
@@ -152,12 +166,12 @@ module Aspera
|
|
|
152
166
|
# start with lower priority : get paths from transfer spec on command line
|
|
153
167
|
@transfer_paths=@transfer_spec_cmdline['paths'] if @transfer_spec_cmdline.has_key?('paths')
|
|
154
168
|
# is there a source list option ?
|
|
155
|
-
file_list
|
|
169
|
+
file_list=options.get_option(:sources,:optional)
|
|
156
170
|
case file_list
|
|
157
171
|
when nil,FILE_LIST_FROM_ARGS
|
|
158
172
|
Log.log.debug("getting file list as parameters")
|
|
159
173
|
# get remaining arguments
|
|
160
|
-
file_list
|
|
174
|
+
file_list=options.get_next_argument("source file list",:multiple)
|
|
161
175
|
raise CliBadArgument,"specify at least one file on command line or use --sources=#{FILE_LIST_FROM_TRANSFER_SPEC} to use transfer spec" if !file_list.is_a?(Array) or file_list.empty?
|
|
162
176
|
when FILE_LIST_FROM_TRANSFER_SPEC
|
|
163
177
|
Log.log.debug("assume list provided in transfer spec")
|
|
@@ -174,7 +188,7 @@ module Aspera
|
|
|
174
188
|
if !@transfer_paths.nil?
|
|
175
189
|
Log.log.warn("--sources overrides paths from --ts")
|
|
176
190
|
end
|
|
177
|
-
case
|
|
191
|
+
case options.get_option(:src_type,:mandatory)
|
|
178
192
|
when :list
|
|
179
193
|
# when providing a list, just specify source
|
|
180
194
|
@transfer_paths=file_list.map{|i|{'source'=>i}}
|
|
@@ -189,20 +203,20 @@ module Aspera
|
|
|
189
203
|
|
|
190
204
|
# start a transfer and wait for completion, plugins shall use this method
|
|
191
205
|
# @param transfer_spec
|
|
192
|
-
# @param
|
|
193
|
-
#
|
|
206
|
+
# @param tr_opts specific options for the transfer_agent
|
|
207
|
+
# tr_opts[:src] specifies how destination_root is set (how transfer spec was generated)
|
|
194
208
|
# other options are carried to specific agent
|
|
195
|
-
def start(transfer_spec,
|
|
209
|
+
def start(transfer_spec,tr_opts)
|
|
196
210
|
# check parameters
|
|
197
211
|
raise "transfer_spec must be hash" unless transfer_spec.is_a?(Hash)
|
|
198
|
-
raise "
|
|
212
|
+
raise "tr_opts must be hash" unless tr_opts.is_a?(Hash)
|
|
199
213
|
# process :src option
|
|
200
214
|
case transfer_spec['direction']
|
|
201
215
|
when 'receive'
|
|
202
216
|
# init default if required in any case
|
|
203
217
|
@transfer_spec_cmdline['destination_root']||=destination_folder(transfer_spec['direction'])
|
|
204
218
|
when 'send'
|
|
205
|
-
case
|
|
219
|
+
case tr_opts[:src]
|
|
206
220
|
when :direct
|
|
207
221
|
# init default if required
|
|
208
222
|
@transfer_spec_cmdline['destination_root']||=destination_folder(transfer_spec['direction'])
|
|
@@ -213,12 +227,12 @@ module Aspera
|
|
|
213
227
|
when :node_gen4
|
|
214
228
|
@transfer_spec_cmdline.delete('destination_root') if @transfer_spec_cmdline.has_key?('destination_root_id')
|
|
215
229
|
else
|
|
216
|
-
raise StandardError,"InternalError: unsupported value: #{
|
|
230
|
+
raise StandardError,"InternalError: unsupported value: #{tr_opts[:src]}"
|
|
217
231
|
end
|
|
218
232
|
end
|
|
219
233
|
|
|
220
234
|
# only used here
|
|
221
|
-
|
|
235
|
+
tr_opts.delete(:src)
|
|
222
236
|
|
|
223
237
|
# update command line paths, unless destination already has one
|
|
224
238
|
@transfer_spec_cmdline['paths']=transfer_spec['paths'] || ts_source_paths
|
|
@@ -227,13 +241,26 @@ module Aspera
|
|
|
227
241
|
# create transfer agent
|
|
228
242
|
self.set_agent_by_options
|
|
229
243
|
Log.log.debug("transfer agent is a #{@agent.class}")
|
|
230
|
-
@agent.start_transfer(transfer_spec,
|
|
244
|
+
@agent.start_transfer(transfer_spec,tr_opts)
|
|
231
245
|
result=@agent.wait_for_transfers_completion
|
|
232
246
|
@progress_listener.reset
|
|
233
247
|
Fasp::Manager.validate_status_list(result)
|
|
248
|
+
send_email_transfer_notification(transfer_spec,result)
|
|
234
249
|
return result
|
|
235
250
|
end
|
|
236
251
|
|
|
252
|
+
def send_email_transfer_notification(transfer_spec,statuses)
|
|
253
|
+
return if options.get_option(:notif_to,:optional).nil?
|
|
254
|
+
global_status=self.class.session_status(statuses)
|
|
255
|
+
email_vars={
|
|
256
|
+
global_transfer_status: global_status,
|
|
257
|
+
subject: "ascli transfer: #{global_status}",
|
|
258
|
+
body: "Transfer is: #{global_status}",
|
|
259
|
+
ts: transfer_spec
|
|
260
|
+
}
|
|
261
|
+
@env[:config].send_email_template(email_vars,DEFAULT_TRANSFER_NOTIF_TMPL)
|
|
262
|
+
end
|
|
263
|
+
|
|
237
264
|
# @return :success if all sessions statuses returned by "start" are success
|
|
238
265
|
# else return the first error exception object
|
|
239
266
|
def self.session_status(statuses)
|
data/lib/aspera/cli/version.rb
CHANGED
|
@@ -4,21 +4,46 @@ module Aspera
|
|
|
4
4
|
# process_param is called repeatedly with all known parameters
|
|
5
5
|
# add_env_args is called to get resulting param list and env var (also checks that all params were used)
|
|
6
6
|
class CommandLineBuilder
|
|
7
|
+
# transform yes/no to trye/false
|
|
8
|
+
def self.yes_to_true(value)
|
|
9
|
+
case value
|
|
10
|
+
when 'yes'; return true
|
|
11
|
+
when 'no'; return false
|
|
12
|
+
end
|
|
13
|
+
raise "unsupported value: #{value}"
|
|
14
|
+
end
|
|
7
15
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
# Called by provider of definition before constructor of this class so that params_definition has all mandatory fields
|
|
17
|
+
def self.normalize_description(d)
|
|
18
|
+
d.each do |param_name,options|
|
|
19
|
+
Log.log.debug("def: #{param_name}")
|
|
20
|
+
raise "Expecting Hash, but have #{options.class} in #{param_name}" unless options.is_a?(Hash)
|
|
21
|
+
#options[:accepted_types]=:bool if options[:cltype].eql?(:envvar) and !options.has_key?(:accepted_types)
|
|
22
|
+
# by default : not mandatory
|
|
23
|
+
options[:mandatory]||=false
|
|
24
|
+
options[:desc]||=''
|
|
25
|
+
# by default : string, unless it's without arg
|
|
26
|
+
if ! options.has_key?(:accepted_types)
|
|
27
|
+
options[:accepted_types]=options[:cltype].eql?(:opt_without_arg) ? :bool : :string
|
|
28
|
+
end
|
|
29
|
+
# single type is placed in array
|
|
30
|
+
options[:accepted_types]=[options[:accepted_types]] unless options[:accepted_types].is_a?(Array)
|
|
31
|
+
if !options.has_key?(:option_switch) and options.has_key?(:cltype) and [:opt_without_arg,:opt_with_arg].include?(options[:cltype])
|
|
32
|
+
options[:option_switch]='--'+param_name.to_s.gsub('_','-')
|
|
33
|
+
end
|
|
34
|
+
end
|
|
13
35
|
end
|
|
14
36
|
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# clvarname : command line variable name
|
|
15
40
|
def env_name(param_name,options)
|
|
16
|
-
return options[:
|
|
41
|
+
return options[:clvarname]
|
|
17
42
|
end
|
|
18
43
|
|
|
19
44
|
public
|
|
20
45
|
|
|
21
|
-
|
|
46
|
+
attr_reader :params_definition
|
|
22
47
|
|
|
23
48
|
# @param param_hash
|
|
24
49
|
def initialize(param_hash,params_definition)
|
|
@@ -44,15 +69,6 @@ module Aspera
|
|
|
44
69
|
return nil
|
|
45
70
|
end
|
|
46
71
|
|
|
47
|
-
# transform yes/no to trye/false
|
|
48
|
-
def self.yes_to_true(value)
|
|
49
|
-
case value
|
|
50
|
-
when 'yes'; return true
|
|
51
|
-
when 'no'; return false
|
|
52
|
-
end
|
|
53
|
-
raise "unsupported value: #{value}"
|
|
54
|
-
end
|
|
55
|
-
|
|
56
72
|
# add options directly to ascp command line
|
|
57
73
|
def add_command_line_options(options)
|
|
58
74
|
return if options.nil?
|
|
@@ -71,24 +87,25 @@ module Aspera
|
|
|
71
87
|
# @param options : options for type
|
|
72
88
|
def process_param(param_name,action=nil)
|
|
73
89
|
options=@params_definition[param_name]
|
|
74
|
-
action=options[:
|
|
90
|
+
action=options[:cltype] if action.nil?
|
|
75
91
|
# should not happen
|
|
76
92
|
raise "Internal error: ask processing of param #{param_name}" if options.nil?
|
|
77
|
-
# by default : not mandatory
|
|
78
|
-
options[:mandatory]||=false
|
|
79
|
-
if options.has_key?(:accepted_types)
|
|
80
|
-
# single type is placed in array
|
|
81
|
-
options[:accepted_types]=[options[:accepted_types]] unless options[:accepted_types].is_a?(Array)
|
|
82
|
-
else
|
|
83
|
-
# by default : string, unless it's without arg
|
|
84
|
-
options[:accepted_types]=action.eql?(:opt_without_arg) ? BOOLEAN_CLASSES : [String]
|
|
85
|
-
end
|
|
86
93
|
# check mandatory parameter (nil is valid value)
|
|
87
94
|
raise Fasp::Error.new("mandatory parameter: #{param_name}") if options[:mandatory] and !@param_hash.has_key?(param_name)
|
|
88
95
|
parameter_value=@param_hash[param_name]
|
|
89
|
-
parameter_value=options[:default] if parameter_value.nil? and options.has_key?(:default)
|
|
96
|
+
#parameter_value=options[:default] if parameter_value.nil? and options.has_key?(:default)
|
|
97
|
+
expected_classes=options[:accepted_types].map do |s|
|
|
98
|
+
case s
|
|
99
|
+
when :string; String
|
|
100
|
+
when :array; Array
|
|
101
|
+
when :hash; Hash
|
|
102
|
+
when :int; Integer
|
|
103
|
+
when :bool; [TrueClass,FalseClass]
|
|
104
|
+
else raise "INTERNAL: unexpected value: #{s}"
|
|
105
|
+
end
|
|
106
|
+
end.flatten
|
|
90
107
|
# check provided type
|
|
91
|
-
raise Fasp::Error.new("#{param_name} is : #{parameter_value.class} (#{parameter_value}), shall be #{options[:accepted_types]}, ") unless parameter_value.nil? or
|
|
108
|
+
raise Fasp::Error.new("#{param_name} is : #{parameter_value.class} (#{parameter_value}), shall be #{options[:accepted_types]}, ") unless parameter_value.nil? or expected_classes.include?(parameter_value.class)
|
|
92
109
|
@used_param_names.push(param_name) unless action.eql?(:defer)
|
|
93
110
|
|
|
94
111
|
# process only non-nil values
|
|
@@ -102,7 +119,8 @@ module Aspera
|
|
|
102
119
|
end
|
|
103
120
|
raise "unsupported value: #{parameter_value}" unless options[:accepted_values].nil? or options[:accepted_values].include?(parameter_value)
|
|
104
121
|
if options[:encode]
|
|
105
|
-
|
|
122
|
+
# :encode has name of class with encoding method
|
|
123
|
+
newvalue=Kernel.const_get(options[:encode]).send("encode_#{param_name}",parameter_value)
|
|
106
124
|
raise Fasp::Error.new("unsupported #{param_name}: #{parameter_value}") if newvalue.nil?
|
|
107
125
|
parameter_value=newvalue
|
|
108
126
|
end
|
|
@@ -123,12 +141,12 @@ module Aspera
|
|
|
123
141
|
else raise Fasp::Error.new("unsupported #{param_name}: #{parameter_value}")
|
|
124
142
|
end
|
|
125
143
|
add_param=!add_param if options[:add_on_false]
|
|
126
|
-
add_command_line_options([
|
|
144
|
+
add_command_line_options([options[:option_switch]]) if add_param
|
|
127
145
|
when :opt_with_arg # transform into command line option with value
|
|
128
146
|
#parameter_value=parameter_value.to_s if parameter_value.is_a?(Integer)
|
|
129
147
|
parameter_value=[parameter_value] unless parameter_value.is_a?(Array)
|
|
130
148
|
# if transfer_spec value is an array, applies option many times
|
|
131
|
-
parameter_value.each{|v|add_command_line_options([
|
|
149
|
+
parameter_value.each{|v|add_command_line_options([options[:option_switch],v])}
|
|
132
150
|
else
|
|
133
151
|
raise "Error"
|
|
134
152
|
end
|
|
@@ -4,6 +4,7 @@ require 'aspera/temp_file_manager'
|
|
|
4
4
|
require 'securerandom'
|
|
5
5
|
require 'base64'
|
|
6
6
|
require 'json'
|
|
7
|
+
require 'yaml'
|
|
7
8
|
require 'securerandom'
|
|
8
9
|
require 'fileutils'
|
|
9
10
|
|
|
@@ -12,97 +13,67 @@ module Aspera
|
|
|
12
13
|
# translate transfer specification to ascp parameter list
|
|
13
14
|
class Parameters
|
|
14
15
|
private
|
|
15
|
-
#
|
|
16
|
+
# Temp folder for file lists, must contain only file lists
|
|
16
17
|
# because of garbage collection takes any file there
|
|
17
18
|
# this could be refined, as , for instance, on macos, temp folder is already user specific
|
|
18
19
|
@@file_list_folder=TempFileManager.instance.new_file_path_global('asession_filelists')
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
'
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
'EX_apply_local_docroot' => { :type => :opt_without_arg, :option_switch=>'--apply-local-docroot'},
|
|
72
|
-
# TODO: manage those parameters, some are for connect only ? node api ?
|
|
73
|
-
'target_rate_cap_kbps' => { :type => :ignore, :accepted_types=>Integer},
|
|
74
|
-
'target_rate_percentage' => { :type => :ignore, :accepted_types=>String}, # -wf -l<rate>p
|
|
75
|
-
'min_rate_cap_kbps' => { :type => :ignore, :accepted_types=>Integer},
|
|
76
|
-
'rate_policy_allowed' => { :type => :ignore, :accepted_types=>String},
|
|
77
|
-
'fasp_url' => { :type => :ignore, :accepted_types=>String},
|
|
78
|
-
'lock_rate_policy' => { :type => :ignore, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
|
|
79
|
-
'lock_min_rate' => { :type => :ignore, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
|
|
80
|
-
'lock_target_rate' => { :type => :ignore, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
|
|
81
|
-
'authentication' => { :type => :ignore, :accepted_types=>String}, # value = token
|
|
82
|
-
'https_fallback_port' => { :type => :ignore, :accepted_types=>Integer}, # same as http fallback, option -t ?
|
|
83
|
-
'content_protection' => { :type => :ignore, :accepted_types=>String},
|
|
84
|
-
'cipher_allowed' => { :type => :ignore, :accepted_types=>String},
|
|
85
|
-
'multi_session' => { :type => :ignore, :accepted_types=>Integer}, # managed
|
|
86
|
-
'obfuscate_file_names' => { :type => :ignore, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
|
|
87
|
-
# optional tags ( additional option to generate: {:space=>' ',:object_nl=>' ',:space_before=>'+',:array_nl=>'1'} )
|
|
88
|
-
'tags' => { :type => :opt_with_arg, :option_switch=>'--tags64',:accepted_types=>Hash,:encode=>lambda{|tags|Base64.strict_encode64(JSON.generate(tags))}},
|
|
89
|
-
# special processing @builder.process_param( called individually
|
|
90
|
-
'use_ascp4' => { :type => :defer, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
|
|
91
|
-
'paths' => { :type => :defer, :accepted_types=>Array},
|
|
92
|
-
'EX_file_list' => { :type => :defer, :option_switch=>'--file-list', :accepted_types=>String},
|
|
93
|
-
'EX_file_pair_list' => { :type => :defer, :option_switch=>'--file-pair-list', :accepted_types=>String},
|
|
94
|
-
'EX_ascp_args' => { :type => :defer, :accepted_types=>Array},
|
|
95
|
-
'destination_root' => { :type => :defer, :accepted_types=>String},
|
|
96
|
-
'wss_enabled' => { :type => :defer, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
|
|
97
|
-
'wss_port' => { :type => :defer, :accepted_types=>Integer},
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
private_constant :PARAM_DEFINITION
|
|
20
|
+
@@param_description_cache=nil
|
|
21
|
+
# @return normaiwed description of transfer spec parameters
|
|
22
|
+
def self.description
|
|
23
|
+
return @@param_description_cache unless @@param_description_cache.nil?
|
|
24
|
+
# config file in same folder with same name as this source
|
|
25
|
+
@@param_description_cache=YAML.load_file("#{__FILE__[0..-3]}yaml")
|
|
26
|
+
Aspera::CommandLineBuilder.normalize_description(@@param_description_cache)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Agents shown in manual
|
|
30
|
+
SUPPORTED_AGENTS=[:direct,:node,:connect]
|
|
31
|
+
# Short names of columns in manual
|
|
32
|
+
SUPPORTED_AGENTS_SHORT=SUPPORTED_AGENTS.map{|a|a.to_s[0].to_sym}
|
|
33
|
+
|
|
34
|
+
# @return a table suitable to display a manual
|
|
35
|
+
def self.man_table
|
|
36
|
+
result=[]
|
|
37
|
+
description.keys.map do |k|
|
|
38
|
+
i=description[k]
|
|
39
|
+
param={name: k, type: [i[:accepted_types]].flatten.join(','),description: i[:desc]}
|
|
40
|
+
SUPPORTED_AGENTS.each do |a|
|
|
41
|
+
param[a.to_s[0].to_sym]=i[:context].nil? || i[:context].include?(a) ? 'Y' : ''
|
|
42
|
+
end
|
|
43
|
+
# only keep lines that are usable in supported agents
|
|
44
|
+
next if SUPPORTED_AGENTS_SHORT.inject(true){|m,i|m and param[i].empty?}
|
|
45
|
+
param[:cli]=case i[:cltype]
|
|
46
|
+
when :envvar; 'env:'+i[:clvarname]
|
|
47
|
+
when :opt_without_arg,:opt_with_arg; i[:option_switch]
|
|
48
|
+
else ''
|
|
49
|
+
end
|
|
50
|
+
if i.has_key?(:enum)
|
|
51
|
+
param[:description] << "\nAllowed values: #{i[:enum].join(', ')}"
|
|
52
|
+
end
|
|
53
|
+
result.push(param)
|
|
54
|
+
end
|
|
55
|
+
return result
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# special encoding methods used in YAML (key: :encode)
|
|
59
|
+
def self.encode_cipher(v)
|
|
60
|
+
v.tr('-','')
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# special encoding methods used in YAML (key: :encode)
|
|
64
|
+
def self.encode_source_root(v)
|
|
65
|
+
Base64.strict_encode64(v)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# special encoding methods used in YAML (key: :encode)
|
|
69
|
+
def self.encode_tags(v)
|
|
70
|
+
Base64.strict_encode64(JSON.generate(v))
|
|
71
|
+
end
|
|
101
72
|
|
|
102
73
|
def initialize(job_spec,options)
|
|
103
74
|
@job_spec=job_spec
|
|
104
|
-
@builder=Aspera::CommandLineBuilder.new(@job_spec,PARAM_DEFINITION)
|
|
105
75
|
@options=options
|
|
76
|
+
@builder=Aspera::CommandLineBuilder.new(@job_spec,self.class.description)
|
|
106
77
|
end
|
|
107
78
|
|
|
108
79
|
public
|
|
@@ -125,7 +96,7 @@ module Aspera
|
|
|
125
96
|
# special cases
|
|
126
97
|
@job_spec.delete('source_root') if @job_spec.has_key?('source_root') and @job_spec['source_root'].empty?
|
|
127
98
|
|
|
128
|
-
# use web socket initiation ?
|
|
99
|
+
# use web socket session initiation ?
|
|
129
100
|
if @builder.process_param('wss_enabled',:get_value) and @options[:wss]
|
|
130
101
|
# by default use web socket session if available, unless removed by user
|
|
131
102
|
@builder.add_command_line_options(['--ws-connect'])
|
|
@@ -151,8 +122,7 @@ module Aspera
|
|
|
151
122
|
# destination will be base64 encoded, put before path arguments
|
|
152
123
|
@builder.add_command_line_options(['--dest64'])
|
|
153
124
|
end
|
|
154
|
-
|
|
155
|
-
PARAM_DEFINITION['paths'][:mandatory]=!@job_spec.has_key?('keepalive')
|
|
125
|
+
@builder.params_definition['paths'][:mandatory]=!@job_spec.has_key?('keepalive')
|
|
156
126
|
paths_array=@builder.process_param('paths',:get_value)
|
|
157
127
|
unless paths_array.nil?
|
|
158
128
|
# use file list if there is storage defined for it.
|