aspera-cli 4.5.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.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +1 -0
  3. data/README.md +1894 -1574
  4. data/bin/ascli +21 -1
  5. data/bin/asession +38 -34
  6. data/docs/test_env.conf +14 -3
  7. data/examples/aoc.rb +17 -15
  8. data/examples/dascli +26 -0
  9. data/examples/faspex4.rb +42 -35
  10. data/examples/proxy.pac +1 -1
  11. data/examples/transfer.rb +38 -37
  12. data/lib/aspera/aoc.rb +245 -205
  13. data/lib/aspera/ascmd.rb +111 -90
  14. data/lib/aspera/ats_api.rb +16 -14
  15. data/lib/aspera/cli/basic_auth_plugin.rb +19 -18
  16. data/lib/aspera/cli/extended_value.rb +50 -39
  17. data/lib/aspera/cli/formater.rb +161 -135
  18. data/lib/aspera/cli/info.rb +18 -0
  19. data/lib/aspera/cli/listener/line_dump.rb +4 -2
  20. data/lib/aspera/cli/listener/logger.rb +3 -1
  21. data/lib/aspera/cli/listener/progress.rb +20 -21
  22. data/lib/aspera/cli/listener/progress_multi.rb +29 -31
  23. data/lib/aspera/cli/main.rb +194 -183
  24. data/lib/aspera/cli/manager.rb +213 -206
  25. data/lib/aspera/cli/plugin.rb +71 -49
  26. data/lib/aspera/cli/plugins/alee.rb +8 -7
  27. data/lib/aspera/cli/plugins/aoc.rb +675 -558
  28. data/lib/aspera/cli/plugins/ats.rb +116 -109
  29. data/lib/aspera/cli/plugins/bss.rb +35 -34
  30. data/lib/aspera/cli/plugins/config.rb +722 -542
  31. data/lib/aspera/cli/plugins/console.rb +28 -22
  32. data/lib/aspera/cli/plugins/cos.rb +28 -37
  33. data/lib/aspera/cli/plugins/faspex.rb +281 -227
  34. data/lib/aspera/cli/plugins/faspex5.rb +129 -84
  35. data/lib/aspera/cli/plugins/node.rb +426 -232
  36. data/lib/aspera/cli/plugins/orchestrator.rb +106 -98
  37. data/lib/aspera/cli/plugins/preview.rb +196 -191
  38. data/lib/aspera/cli/plugins/server.rb +131 -126
  39. data/lib/aspera/cli/plugins/shares.rb +49 -36
  40. data/lib/aspera/cli/plugins/sync.rb +27 -28
  41. data/lib/aspera/cli/transfer_agent.rb +84 -79
  42. data/lib/aspera/cli/version.rb +3 -1
  43. data/lib/aspera/colors.rb +37 -28
  44. data/lib/aspera/command_line_builder.rb +84 -63
  45. data/lib/aspera/cos_node.rb +68 -34
  46. data/lib/aspera/data_repository.rb +4 -2
  47. data/lib/aspera/environment.rb +61 -46
  48. data/lib/aspera/fasp/agent_base.rb +36 -31
  49. data/lib/aspera/fasp/agent_connect.rb +44 -37
  50. data/lib/aspera/fasp/agent_direct.rb +101 -104
  51. data/lib/aspera/fasp/agent_httpgw.rb +91 -90
  52. data/lib/aspera/fasp/agent_node.rb +36 -33
  53. data/lib/aspera/fasp/agent_trsdk.rb +28 -31
  54. data/lib/aspera/fasp/error.rb +3 -1
  55. data/lib/aspera/fasp/error_info.rb +81 -54
  56. data/lib/aspera/fasp/installation.rb +171 -151
  57. data/lib/aspera/fasp/listener.rb +2 -0
  58. data/lib/aspera/fasp/parameters.rb +105 -111
  59. data/lib/aspera/fasp/parameters.yaml +305 -249
  60. data/lib/aspera/fasp/resume_policy.rb +20 -20
  61. data/lib/aspera/fasp/transfer_spec.rb +27 -0
  62. data/lib/aspera/fasp/uri.rb +31 -29
  63. data/lib/aspera/faspex_gw.rb +95 -118
  64. data/lib/aspera/hash_ext.rb +12 -13
  65. data/lib/aspera/id_generator.rb +11 -9
  66. data/lib/aspera/keychain/encrypted_hash.rb +73 -57
  67. data/lib/aspera/keychain/macos_security.rb +27 -29
  68. data/lib/aspera/log.rb +40 -39
  69. data/lib/aspera/nagios.rb +24 -22
  70. data/lib/aspera/node.rb +38 -30
  71. data/lib/aspera/oauth.rb +217 -248
  72. data/lib/aspera/open_application.rb +9 -7
  73. data/lib/aspera/persistency_action_once.rb +15 -14
  74. data/lib/aspera/persistency_folder.rb +15 -18
  75. data/lib/aspera/preview/file_types.rb +266 -270
  76. data/lib/aspera/preview/generator.rb +94 -92
  77. data/lib/aspera/preview/image_error.png +0 -0
  78. data/lib/aspera/preview/options.rb +20 -17
  79. data/lib/aspera/preview/utils.rb +99 -102
  80. data/lib/aspera/preview/video_error.png +0 -0
  81. data/lib/aspera/{proxy_auto_config.erb.js → proxy_auto_config.js} +23 -31
  82. data/lib/aspera/proxy_auto_config.rb +114 -21
  83. data/lib/aspera/rest.rb +144 -142
  84. data/lib/aspera/rest_call_error.rb +3 -2
  85. data/lib/aspera/rest_error_analyzer.rb +31 -31
  86. data/lib/aspera/rest_errors_aspera.rb +18 -16
  87. data/lib/aspera/secret_hider.rb +68 -0
  88. data/lib/aspera/ssh.rb +20 -16
  89. data/lib/aspera/sync.rb +57 -54
  90. data/lib/aspera/temp_file_manager.rb +20 -14
  91. data/lib/aspera/timer_limiter.rb +10 -8
  92. data/lib/aspera/uri_reader.rb +14 -15
  93. data/lib/aspera/web_auth.rb +85 -80
  94. data.tar.gz.sig +0 -0
  95. metadata +169 -40
  96. metadata.gz.sig +2 -0
  97. data/bin/dascli +0 -13
  98. data/docs/Makefile +0 -63
  99. data/docs/README.erb.md +0 -4221
  100. data/docs/README.md +0 -13
  101. data/docs/diagrams.txt +0 -49
  102. data/docs/doc_tools.rb +0 -58
  103. data/lib/aspera/cli/plugins/shares2.rb +0 -114
  104. data/lib/aspera/fasp/default.rb +0 -17
@@ -1,4 +1,6 @@
1
- require 'aspera/fasp/parameters'
1
+ # frozen_string_literal: true
2
+
3
+ require 'aspera/fasp/transfer_spec'
2
4
  require 'aspera/cli/listener/logger'
3
5
  require 'aspera/cli/listener/progress_multi'
4
6
 
@@ -9,42 +11,42 @@ module Aspera
9
11
  # provides CLI options to select one of the transfer agents (FASP/ascp client)
10
12
  class TransferAgent
11
13
  # special value for --sources : read file list from arguments
12
- FILE_LIST_FROM_ARGS='@args'
14
+ FILE_LIST_FROM_ARGS = '@args'
13
15
  # special value for --sources : read file list from transfer spec (--ts)
14
- FILE_LIST_FROM_TRANSFER_SPEC='@ts'
15
- DEFAULT_TRANSFER_NOTIF_TMPL=<<END_OF_TEMPLATE
16
- From: <%=from_name%> <<%=from_email%>>
17
- To: <<%=to%>>
18
- Subject: <%=subject%>
16
+ FILE_LIST_FROM_TRANSFER_SPEC = '@ts'
17
+ DEFAULT_TRANSFER_NOTIF_TMPL = <<~END_OF_TEMPLATE
18
+ From: <%=from_name%> <<%=from_email%>>
19
+ To: <<%=to%>>
20
+ Subject: <%=subject%>
19
21
 
20
- Transfer is: <%=global_transfer_status%>
22
+ Transfer is: <%=global_transfer_status%>
21
23
 
22
- <%=ts.to_yaml%>
23
- END_OF_TEMPLATE
24
+ <%=ts.to_yaml%>
25
+ END_OF_TEMPLATE
24
26
  #% (formating bug in eclipse)
25
27
  private_constant :FILE_LIST_FROM_ARGS,:FILE_LIST_FROM_TRANSFER_SPEC,:DEFAULT_TRANSFER_NOTIF_TMPL
26
- TRANSFER_AGENTS=[:direct,:node,:connect,:httpgw,:trsdk]
28
+ TRANSFER_AGENTS = %i[direct node connect httpgw trsdk].freeze
27
29
 
28
30
  # @param env external objects: option manager, config file manager
29
31
  def initialize(opt_mgr,config)
30
- @opt_mgr=opt_mgr
31
- @config=config
32
+ @opt_mgr = opt_mgr
33
+ @config = config
32
34
  # command line can override transfer spec
33
- @transfer_spec_cmdline={'create_dir'=>true}
35
+ @transfer_spec_cmdline = {'create_dir' => true}
34
36
  # the currently selected transfer agent
35
- @agent=nil
36
- @progress_listener=Listener::ProgressMulti.new
37
+ @agent = nil
38
+ @progress_listener = Listener::ProgressMulti.new
37
39
  # source/destination pair, like "paths" of transfer spec
38
- @transfer_paths=nil
40
+ @transfer_paths = nil
39
41
  @opt_mgr.set_obj_attr(:ts,self,:option_transfer_spec)
40
- @opt_mgr.add_opt_simple(:ts,"override transfer spec values (Hash, use @json: prefix), current=#{@opt_mgr.get_option(:ts,:optional)}")
41
- @opt_mgr.add_opt_simple(:local_resume,"set resume policy (Hash, use @json: prefix), current=#{@opt_mgr.get_option(:local_resume,:optional)}")
42
- @opt_mgr.add_opt_simple(:to_folder,"destination folder for downloaded files")
43
- @opt_mgr.add_opt_simple(:sources,"list of source files (see doc)")
44
- @opt_mgr.add_opt_simple(:transfer_info,"parameters for transfer agent")
45
- @opt_mgr.add_opt_list(:src_type,[:list,:pair],"type of file list")
46
- @opt_mgr.add_opt_list(:transfer,TRANSFER_AGENTS,"type of transfer agent")
47
- @opt_mgr.add_opt_list(:progress,[:none,:native,:multi],"type of progress bar")
42
+ @opt_mgr.add_opt_simple(:ts,"override transfer spec values (Hash, use @json: prefix), current=#{@opt_mgr.get_option(:ts)}")
43
+ @opt_mgr.add_opt_simple(:local_resume,"set resume policy (Hash, use @json: prefix), current=#{@opt_mgr.get_option(:local_resume)}")
44
+ @opt_mgr.add_opt_simple(:to_folder,'destination folder for downloaded files')
45
+ @opt_mgr.add_opt_simple(:sources,'list of source files (see doc)')
46
+ @opt_mgr.add_opt_simple(:transfer_info,'parameters for transfer agent')
47
+ @opt_mgr.add_opt_list(:src_type,%i[list pair],'type of file list')
48
+ @opt_mgr.add_opt_list(:transfer,TRANSFER_AGENTS,'type of transfer agent')
49
+ @opt_mgr.add_opt_list(:progress,%i[none native multi],'type of progress bar')
48
50
  @opt_mgr.set_option(:transfer,:direct)
49
51
  @opt_mgr.set_option(:src_type,:list)
50
52
  @opt_mgr.set_option(:progress,:native) # use native ascp progress bar as it is more reliable
@@ -58,12 +60,12 @@ END_OF_TEMPLATE
58
60
 
59
61
  def option_transfer_spec_deep_merge(ts); @transfer_spec_cmdline.deep_merge!(ts); end
60
62
 
61
- def set_agent_instance(instance)
62
- @agent=instance
63
+ def agent_instance=(instance)
64
+ @agent = instance
63
65
  @agent.add_listener(Listener::Logger.new)
64
66
  # use local progress bar if asked so, or if native and non local ascp (because only local ascp has native progress bar)
65
- if @opt_mgr.get_option(:progress,:mandatory).eql?(:multi) or
66
- (@opt_mgr.get_option(:progress,:mandatory).eql?(:native) and ! instance.class.to_s.eql?('Aspera::Fasp::AgentDirect'))
67
+ if @opt_mgr.get_option(:progress,is_type: :mandatory).eql?(:multi) ||
68
+ (@opt_mgr.get_option(:progress,is_type: :mandatory).eql?(:native) && !instance.class.to_s.eql?('Aspera::Fasp::AgentDirect'))
67
69
  @agent.add_listener(@progress_listener)
68
70
  end
69
71
  end
@@ -71,25 +73,27 @@ END_OF_TEMPLATE
71
73
  # analyze options and create new agent if not already created or set
72
74
  def set_agent_by_options
73
75
  return nil unless @agent.nil?
74
- agent_type=@opt_mgr.get_option(:transfer,:mandatory)
76
+ agent_type = @opt_mgr.get_option(:transfer,is_type: :mandatory)
77
+ # agent plugin is loaded on demand to avoid loading unnecessary dependencies
75
78
  require "aspera/fasp/agent_#{agent_type}"
76
- agent_options=@opt_mgr.get_option(:transfer_info,:optional)
77
- raise CliBadArgument,"the transfer agent configuration shall be Hash, not #{agent_options.class} (#{agent_options}), use either @json:<json> or @preset:<parameter set name>" unless [Hash,NilClass].include?(agent_options.class)
79
+ agent_options = @opt_mgr.get_option(:transfer_info)
80
+ raise CliBadArgument,"the transfer agent configuration shall be Hash, not #{agent_options.class} (#{agent_options}), "\
81
+ 'use either @json:<json> or @preset:<parameter set name>' unless [Hash,NilClass].include?(agent_options.class)
78
82
  # special case
79
- if agent_type.eql?(:node) and agent_options.nil?
80
- param_set_name=@config.get_plugin_default_config_name(:node)
81
- raise CliBadArgument,"No default node configured, Please specify --#{:transfer_info.to_s.gsub('_','-')}" if param_set_name.nil?
82
- agent_options=@config.preset_by_name(param_set_name)
83
+ if agent_type.eql?(:node) && agent_options.nil?
84
+ param_set_name = @config.get_plugin_default_config_name(:node)
85
+ raise CliBadArgument,"No default node configured, Please specify --#{:transfer_info.to_s.tr('_','-')}" if param_set_name.nil?
86
+ agent_options = @config.preset_by_name(param_set_name)
83
87
  end
84
88
  # special case
85
- if agent_type.eql?(:direct) and @opt_mgr.get_option(:progress,:mandatory).eql?(:native)
86
- agent_options={} if agent_options.nil?
87
- agent_options[:quiet]=false
89
+ if agent_type.eql?(:direct) && @opt_mgr.get_option(:progress,is_type: :mandatory).eql?(:native)
90
+ agent_options = {} if agent_options.nil?
91
+ agent_options[:quiet] = false
88
92
  end
89
- agent_options=agent_options.symbolize_keys if agent_options.is_a?(Hash)
93
+ agent_options = agent_options.symbolize_keys if agent_options.is_a?(Hash)
90
94
  # get agent instance
91
- new_agent=Kernel.const_get("Aspera::Fasp::Agent#{agent_type.capitalize}").new(agent_options)
92
- set_agent_instance(new_agent)
95
+ new_agent = Kernel.const_get("Aspera::Fasp::Agent#{agent_type.capitalize}").new(agent_options)
96
+ self.agent_instance = new_agent
93
97
  return nil
94
98
  end
95
99
 
@@ -97,14 +101,14 @@ END_OF_TEMPLATE
97
101
  # sets default if needed
98
102
  # param: 'send' or 'receive'
99
103
  def destination_folder(direction)
100
- dest_folder=@opt_mgr.get_option(:to_folder,:optional)
104
+ dest_folder = @opt_mgr.get_option(:to_folder)
101
105
  return File.expand_path(dest_folder) unless dest_folder.nil?
102
- dest_folder=@transfer_spec_cmdline['destination_root']
106
+ dest_folder = @transfer_spec_cmdline['destination_root']
103
107
  return dest_folder unless dest_folder.nil?
104
108
  # default: / on remote, . on local
105
109
  case direction.to_s
106
- when 'send';dest_folder='/'
107
- when 'receive';dest_folder='.'
110
+ when Fasp::TransferSpec::DIRECTION_SEND then dest_folder = '/'
111
+ when Fasp::TransferSpec::DIRECTION_RECEIVE then dest_folder = '.'
108
112
  else raise "wrong direction: #{direction}"
109
113
  end
110
114
  return dest_folder
@@ -112,45 +116,46 @@ END_OF_TEMPLATE
112
116
 
113
117
  # This is how the list of files to be transfered is specified
114
118
  # get paths suitable for transfer spec from command line
115
- # @return {:source=>(mandatory), :destination=>(optional)}
119
+ # @return {source: (mandatory), destination: (optional)}
116
120
  # computation is done only once, cache is kept in @transfer_paths
117
121
  def ts_source_paths
118
122
  # return cache if set
119
123
  return @transfer_paths unless @transfer_paths.nil?
120
124
  # start with lower priority : get paths from transfer spec on command line
121
- @transfer_paths=@transfer_spec_cmdline['paths'] if @transfer_spec_cmdline.has_key?('paths')
125
+ @transfer_paths = @transfer_spec_cmdline['paths'] if @transfer_spec_cmdline.has_key?('paths')
122
126
  # is there a source list option ?
123
- file_list=@opt_mgr.get_option(:sources,:optional)
127
+ file_list = @opt_mgr.get_option(:sources)
124
128
  case file_list
125
129
  when nil,FILE_LIST_FROM_ARGS
126
- Log.log.debug("getting file list as parameters")
130
+ Log.log.debug('getting file list as parameters')
127
131
  # get remaining arguments
128
- file_list=@opt_mgr.get_next_argument("source file list",:multiple)
129
- 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?
132
+ file_list = @opt_mgr.get_next_argument('source file list',expected: :multiple)
133
+ raise CliBadArgument,'specify at least one file on command line or use '\
134
+ "--sources=#{FILE_LIST_FROM_TRANSFER_SPEC} to use transfer spec" if !file_list.is_a?(Array) || file_list.empty?
130
135
  when FILE_LIST_FROM_TRANSFER_SPEC
131
- Log.log.debug("assume list provided in transfer spec")
132
- special_case_direct_with_list=@opt_mgr.get_option(:transfer,:mandatory).eql?(:direct) and Fasp::Parameters.ts_has_file_list(@transfer_spec_cmdline)
133
- raise CliBadArgument,"transfer spec on command line must have sources" if @transfer_paths.nil? and !special_case_direct_with_list
136
+ Log.log.debug('assume list provided in transfer spec')
137
+ (special_case_direct_with_list = @opt_mgr.get_option(:transfer,is_type: :mandatory).eql?(:direct)) && Fasp::Parameters.ts_has_file_list(@transfer_spec_cmdline)
138
+ raise CliBadArgument,'transfer spec on command line must have sources' if @transfer_paths.nil? && !special_case_direct_with_list
134
139
  # here we assume check of sources is made in transfer agent
135
140
  return @transfer_paths
136
141
  when Array
137
- Log.log.debug("getting file list as extended value")
138
- raise CliBadArgument,"sources must be a Array of String" if !file_list.select{|f|!f.is_a?(String)}.empty?
142
+ Log.log.debug('getting file list as extended value')
143
+ raise CliBadArgument,'sources must be a Array of String' if !file_list.reject{|f|f.is_a?(String)}.empty?
139
144
  else
140
145
  raise CliBadArgument,"sources must be a Array, not #{file_list.class}"
141
146
  end
142
147
  # here, file_list is an Array or String
143
148
  if !@transfer_paths.nil?
144
- Log.log.warn("--sources overrides paths from --ts")
149
+ Log.log.warn('--sources overrides paths from --ts')
145
150
  end
146
- case @opt_mgr.get_option(:src_type,:mandatory)
151
+ case @opt_mgr.get_option(:src_type,is_type: :mandatory)
147
152
  when :list
148
153
  # when providing a list, just specify source
149
- @transfer_paths=file_list.map{|i|{'source'=>i}}
154
+ @transfer_paths = file_list.map{|i|{'source' => i}}
150
155
  when :pair
151
156
  raise CliBadArgument,"When using pair, provide an even number of paths: #{file_list.length}" unless file_list.length.even?
152
- @transfer_paths=file_list.each_slice(2).to_a.map{|s,d|{'source'=>s,'destination'=>d}}
153
- else raise "Unsupported src_type"
157
+ @transfer_paths = file_list.each_slice(2).to_a.map{|s,d|{'source' => s,'destination' => d}}
158
+ else raise 'Unsupported src_type'
154
159
  end
155
160
  Log.log.debug("paths=#{@transfer_paths}")
156
161
  return @transfer_paths
@@ -163,18 +168,18 @@ END_OF_TEMPLATE
163
168
  # other options are carried to specific agent
164
169
  def start(transfer_spec,tr_opts)
165
170
  # check parameters
166
- raise "transfer_spec must be hash" unless transfer_spec.is_a?(Hash)
167
- raise "tr_opts must be hash" unless tr_opts.is_a?(Hash)
171
+ raise 'transfer_spec must be hash' unless transfer_spec.is_a?(Hash)
172
+ raise 'tr_opts must be hash' unless tr_opts.is_a?(Hash)
168
173
  # process :src option
169
174
  case transfer_spec['direction']
170
- when 'receive'
175
+ when Fasp::TransferSpec::DIRECTION_RECEIVE
171
176
  # init default if required in any case
172
- @transfer_spec_cmdline['destination_root']||=destination_folder(transfer_spec['direction'])
173
- when 'send'
177
+ @transfer_spec_cmdline['destination_root'] ||= destination_folder(transfer_spec['direction'])
178
+ when Fasp::TransferSpec::DIRECTION_SEND
174
179
  case tr_opts[:src]
175
180
  when :direct
176
181
  # init default if required
177
- @transfer_spec_cmdline['destination_root']||=destination_folder(transfer_spec['direction'])
182
+ @transfer_spec_cmdline['destination_root'] ||= destination_folder(transfer_spec['direction'])
178
183
  when :node_gen3
179
184
  # in that case, destination is set in return by application (API/upload_setup)
180
185
  # but to_folder was used in initial API call
@@ -190,14 +195,15 @@ END_OF_TEMPLATE
190
195
  tr_opts.delete(:src)
191
196
 
192
197
  # update command line paths, unless destination already has one
193
- @transfer_spec_cmdline['paths']=transfer_spec['paths'] || ts_source_paths
198
+ @transfer_spec_cmdline['paths'] = transfer_spec['paths'] || ts_source_paths
194
199
 
195
200
  transfer_spec.merge!(@transfer_spec_cmdline)
196
201
  # create transfer agent
197
- self.set_agent_by_options
202
+ set_agent_by_options
198
203
  Log.log.debug("transfer agent is a #{@agent.class}")
199
204
  @agent.start_transfer(transfer_spec,tr_opts)
200
- result=@agent.wait_for_transfers_completion
205
+ # list of : :success or error message
206
+ result = @agent.wait_for_transfers_completion
201
207
  @progress_listener.reset
202
208
  Fasp::AgentBase.validate_status_list(result)
203
209
  send_email_transfer_notification(transfer_spec,result)
@@ -205,13 +211,13 @@ END_OF_TEMPLATE
205
211
  end
206
212
 
207
213
  def send_email_transfer_notification(transfer_spec,statuses)
208
- return if @opt_mgr.get_option(:notif_to,:optional).nil?
209
- global_status=self.class.session_status(statuses)
210
- email_vars={
214
+ return if @opt_mgr.get_option(:notif_to).nil?
215
+ global_status = self.class.session_status(statuses)
216
+ email_vars = {
211
217
  global_transfer_status: global_status,
212
- subject: "ascli transfer: #{global_status}",
213
- body: "Transfer is: #{global_status}",
214
- ts: transfer_spec
218
+ subject: "ascli transfer: #{global_status}",
219
+ body: "Transfer is: #{global_status}",
220
+ ts: transfer_spec
215
221
  }
216
222
  @config.send_email_template(email_vars,DEFAULT_TRANSFER_NOTIF_TMPL)
217
223
  end
@@ -219,7 +225,7 @@ END_OF_TEMPLATE
219
225
  # @return :success if all sessions statuses returned by "start" are success
220
226
  # else return the first error exception object
221
227
  def self.session_status(statuses)
222
- error_statuses=statuses.select{|i|!i.eql?(:success)}
228
+ error_statuses = statuses.reject{|i|i.eql?(:success)}
223
229
  return :success if error_statuses.empty?
224
230
  return error_statuses.first
225
231
  end
@@ -228,7 +234,6 @@ END_OF_TEMPLATE
228
234
  def shutdown
229
235
  @agent.shutdown if @agent.respond_to?(:shutdown)
230
236
  end
231
-
232
237
  end
233
238
  end
234
239
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aspera
2
4
  module Cli
3
- VERSION = "4.5.0"
5
+ VERSION = '4.8.0'
4
6
  end
5
7
  end
data/lib/aspera/colors.rb CHANGED
@@ -1,43 +1,52 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # simple vt100 colors
2
4
  class String
3
- private
4
- def self.vtcmd(code);"\e[#{code}m";end
5
+ class << self
6
+ private
7
+
8
+ def vtcmd(code);"\e[#{code}m";end
9
+ end
5
10
  # see https://en.wikipedia.org/wiki/ANSI_escape_code
6
11
  # symbol is the method name added to String
7
12
  # it adds control chars to set color (and reset at the end).
8
13
  VTSTYLES = {
9
- :bold=>1,
10
- :italic=>3,
11
- :underline=>4,
12
- :blink=>5,
13
- :reverse_color=>7,
14
- :black=>30,
15
- :red=>31,
16
- :green=>32,
17
- :brown=>33,
18
- :blue=>34,
19
- :magenta=>35,
20
- :cyan=>36,
21
- :gray=>37,
22
- :bg_black=>40,
23
- :bg_red=>41,
24
- :bg_green=>42,
25
- :bg_brown=>43,
26
- :bg_blue=>44,
27
- :bg_magenta=>45,
28
- :bg_cyan=>46,
29
- :bg_gray=>47,
30
- }
14
+ bold: 1,
15
+ italic: 3,
16
+ underline: 4,
17
+ blink: 5,
18
+ reverse_color: 7,
19
+ black: 30,
20
+ red: 31,
21
+ green: 32,
22
+ brown: 33,
23
+ blue: 34,
24
+ magenta: 35,
25
+ cyan: 36,
26
+ gray: 37,
27
+ bg_black: 40,
28
+ bg_red: 41,
29
+ bg_green: 42,
30
+ bg_brown: 43,
31
+ bg_blue: 44,
32
+ bg_magenta: 45,
33
+ bg_cyan: 46,
34
+ bg_gray: 47
35
+ }.freeze
31
36
  private_constant :VTSTYLES
32
37
  # defines methods to String, one per entry in VTSTYLES
33
38
  VTSTYLES.each do |name,code|
34
- begin_seq=vtcmd(code)
35
- end_seq=vtcmd((code >= 10) ? 0 : code+20+(code.eql?(1)?1:0))
36
- if STDERR.tty?
39
+ if $stderr.tty?
40
+ begin_seq = vtcmd(code)
41
+ end_code = 0 # by default reset all
42
+ if code <= 7 then 20 + code
43
+ elsif code <= 37 then 39
44
+ elsif code <= 47 then 49
45
+ end
46
+ end_seq = vtcmd(end_code)
37
47
  define_method(name){"#{begin_seq}#{self}#{end_seq}"}
38
48
  else
39
49
  define_method(name){self}
40
50
  end
41
- public name
42
51
  end
43
52
  end
@@ -1,42 +1,49 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aspera
2
4
  # helper class to build command line from a parameter list (key-value hash)
3
5
  # constructor takes hash: { 'param1':'value1', ...}
4
6
  # process_param is called repeatedly with all known parameters
5
7
  # add_env_args is called to get resulting param list and env var (also checks that all params were used)
6
8
  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
9
+ # parameter with onne of those tags is an ascp command line option with --
10
+ CLTYPE_OPTIONS=%i[opt_without_arg opt_with_arg].freeze
11
+ class<<self
12
+ # transform yes/no to true/false
13
+ def yes_to_true(value)
14
+ case value
15
+ when 'yes' then return true
16
+ when 'no' then return false
17
+ end
18
+ raise "unsupported value: #{value}"
12
19
  end
13
- raise "unsupported value: #{value}"
14
- end
15
20
 
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
- raise "Expecting Hash, but have #{options.class} in #{param_name}" unless options.is_a?(Hash)
20
- #options[:accepted_types]=:bool if options[:cltype].eql?(:envvar) and !options.has_key?(:accepted_types)
21
- # by default : not mandatory
22
- options[:mandatory]||=false
23
- options[:desc]||=''
24
- # by default : string, unless it's without arg
25
- if ! options.has_key?(:accepted_types)
26
- options[:accepted_types]=options[:cltype].eql?(:opt_without_arg) ? :bool : :string
27
- end
28
- # single type is placed in array
29
- options[:accepted_types]=[options[:accepted_types]] unless options[:accepted_types].is_a?(Array)
30
- if !options.has_key?(:option_switch) and options.has_key?(:cltype) and [:opt_without_arg,:opt_with_arg].include?(options[:cltype])
31
- options[:option_switch]='--'+param_name.to_s.gsub('_','-')
21
+ # Called by provider of definition before constructor of this class so that params_definition has all mandatory fields
22
+ def normalize_description(d)
23
+ d.each do |param_name,options|
24
+ raise "Expecting Hash, but have #{options.class} in #{param_name}" unless options.is_a?(Hash)
25
+ #options[:accepted_types]=:bool if options[:cltype].eql?(:envvar) and !options.has_key?(:accepted_types)
26
+ # by default : not mandatory
27
+ options[:mandatory] ||= false
28
+ options[:desc] ||= ''
29
+ # by default : string, unless it's without arg
30
+ if !options.has_key?(:accepted_types)
31
+ options[:accepted_types] = options[:cltype].eql?(:opt_without_arg) ? :bool : :string
32
+ end
33
+ # single type is placed in array
34
+ options[:accepted_types] = [options[:accepted_types]] unless options[:accepted_types].is_a?(Array)
35
+ # add default switch name if not present
36
+ if !options.has_key?(:clswitch) && options.has_key?(:cltype) && CLTYPE_OPTIONS.include?(options[:cltype])
37
+ options[:clswitch] = '--' + param_name.to_s.tr('_','-')
38
+ end
32
39
  end
33
40
  end
34
- end
41
+ end
35
42
 
36
43
  private
37
44
 
38
45
  # clvarname : command line variable name
39
- def env_name(param_name,options)
46
+ def env_name(_param_name,options)
40
47
  return options[:clvarname]
41
48
  end
42
49
 
@@ -46,11 +53,11 @@ module Aspera
46
53
 
47
54
  # @param param_hash
48
55
  def initialize(param_hash,params_definition)
49
- @param_hash=param_hash # keep reference so that it can be modified by caller before calling `process_params`
50
- @params_definition=params_definition
51
- @result_env={}
52
- @result_args=[]
53
- @used_param_names=[]
56
+ @param_hash = param_hash # keep reference so that it can be modified by caller before calling `process_params`
57
+ @params_definition = params_definition
58
+ @result_env = {}
59
+ @result_args = []
60
+ @used_param_names = []
54
61
  end
55
62
 
56
63
  def warn_unrecognized_params
@@ -85,43 +92,55 @@ module Aspera
85
92
  # @param action : type of processing: ignore getvalue envvar opt_without_arg opt_with_arg defer
86
93
  # @param options : options for type
87
94
  def process_param(param_name,action=nil)
88
- options=@params_definition[param_name]
89
- action=options[:cltype] if action.nil?
95
+ options = @params_definition[param_name]
90
96
  # should not happen
91
- raise "Internal error: ask processing of param #{param_name}" if options.nil?
97
+ if options.nil?
98
+ Log.log.warn("Unknown parameter #{param_name}")
99
+ return
100
+ end
101
+ action = options[:cltype] if action.nil?
92
102
  # check mandatory parameter (nil is valid value)
93
- raise Fasp::Error.new("mandatory parameter: #{param_name}") if options[:mandatory] and !@param_hash.has_key?(param_name)
94
- parameter_value=@param_hash[param_name]
103
+ raise Fasp::Error, "Missing mandatory parameter: #{param_name}" if options[:mandatory] && !@param_hash.has_key?(param_name)
104
+ parameter_value = @param_hash[param_name]
105
+
95
106
  #parameter_value=options[:default] if parameter_value.nil? and options.has_key?(:default)
96
- expected_classes=options[:accepted_types].map do |s|
107
+
108
+ # Check parameter type
109
+ expected_classes = options[:accepted_types].map do |s|
97
110
  case s
98
- when :string; String
99
- when :array; Array
100
- when :hash; Hash
101
- when :int; Integer
102
- when :bool; [TrueClass,FalseClass]
111
+ when :string then String
112
+ when :array then Array
113
+ when :hash then Hash
114
+ when :int then Integer
115
+ when :bool then [TrueClass,FalseClass]
103
116
  else raise "INTERNAL: unexpected value: #{s}"
104
117
  end
105
118
  end.flatten
106
- # check provided type
107
- 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)
119
+ raise Fasp::Error,"#{param_name} is : #{parameter_value.class} (#{parameter_value}), shall be #{options[:accepted_types]}, " \
120
+ unless parameter_value.nil? || expected_classes.include?(parameter_value.class)
108
121
  @used_param_names.push(param_name) unless action.eql?(:defer)
109
122
 
110
123
  # process only non-nil values
111
124
  return nil if parameter_value.nil?
112
125
 
113
- if options.has_key?(:translate_values)
126
+ # check that value is of an accepted type (string, int bool)
127
+ raise "Value #{parameter_value} is not allowed for #{param_name}" if options.has_key?(:enum) && !options[:enum].include?(parameter_value)
128
+
129
+ # convert some values if value on command line needs processing from value in structure
130
+ case options[:clconvert]
131
+ when Hash
114
132
  # translate using conversion table
115
- new_value=options[:translate_values][parameter_value]
116
- raise "unsupported value: #{parameter_value}" if new_value.nil?
117
- parameter_value=new_value
118
- end
119
- raise "unsupported value: #{parameter_value}" unless options[:accepted_values].nil? or options[:accepted_values].include?(parameter_value)
120
- if options[:encode]
121
- # :encode has name of class with encoding method
122
- newvalue=Kernel.const_get(options[:encode]).send("encode_#{param_name}",parameter_value)
123
- raise Fasp::Error.new("unsupported #{param_name}: #{parameter_value}") if newvalue.nil?
124
- parameter_value=newvalue
133
+ new_value = options[:clconvert][parameter_value]
134
+ raise "unsupported value: #{parameter_value}, expect: #{options[:clconvert].keys.join(', ')}" if new_value.nil?
135
+ parameter_value = new_value
136
+ when String
137
+ # :clconvert has name of class and encoding method
138
+ convclass,convmethod = options[:clconvert].split('.')
139
+ newvalue = Kernel.const_get(convclass).send(convmethod,parameter_value)
140
+ raise Fasp::Error, "unsupported #{param_name}: #{parameter_value}" if newvalue.nil?
141
+ parameter_value = newvalue
142
+ when NilClass
143
+ else raise "not expected type for clconvert #{options[:clconvert].class} for #{param_name}"
125
144
  end
126
145
 
127
146
  case action
@@ -133,21 +152,23 @@ module Aspera
133
152
  # define ascp parameter in env var from transfer spec
134
153
  @result_env[env_name(param_name,options)] = parameter_value
135
154
  when :opt_without_arg # if present and true : just add option without value
136
- add_param=false
155
+ add_param = false
137
156
  case parameter_value
138
- when false# nothing to put on command line, no creation by default
139
- when true; add_param=true
140
- else raise Fasp::Error.new("unsupported #{param_name}: #{parameter_value}")
157
+ when false then nil # nothing to put on command line, no creation by default
158
+ when true then add_param = true
159
+ else raise Fasp::Error, "unsupported #{param_name}: #{parameter_value}"
141
160
  end
142
- add_param=!add_param if options[:add_on_false]
143
- add_command_line_options([options[:option_switch]]) if add_param
161
+ add_param = !add_param if options[:add_on_false]
162
+ add_command_line_options([options[:clswitch]]) if add_param
144
163
  when :opt_with_arg # transform into command line option with value
145
164
  #parameter_value=parameter_value.to_s if parameter_value.is_a?(Integer)
146
- parameter_value=[parameter_value] unless parameter_value.is_a?(Array)
165
+ parameter_value = [parameter_value] unless parameter_value.is_a?(Array)
147
166
  # if transfer_spec value is an array, applies option many times
148
- parameter_value.each{|v|add_command_line_options([options[:option_switch],v])}
167
+ parameter_value.each{|v|add_command_line_options([options[:clswitch],v])}
168
+ when NilClass
169
+ Log.log.debug("Ignoring parameter: #{param_name}")
149
170
  else
150
- raise "Error"
171
+ raise "ERROR: unknown action: #{action}/#{action.class}"
151
172
  end
152
173
  end
153
174
  end