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.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +1267 -999
  4. data/bin/ascli +20 -1
  5. data/bin/asession +37 -34
  6. data/docs/test_env.conf +7 -3
  7. data/examples/aoc.rb +13 -12
  8. data/examples/dascli +23 -0
  9. data/examples/faspex4.rb +34 -29
  10. data/examples/{transfer.rb → node.rb} +31 -59
  11. data/examples/server.rb +93 -0
  12. data/lib/aspera/aoc.rb +153 -143
  13. data/lib/aspera/ascmd.rb +56 -45
  14. data/lib/aspera/ats_api.rb +9 -6
  15. data/lib/aspera/cli/basic_auth_plugin.rb +18 -16
  16. data/lib/aspera/cli/extended_value.rb +33 -30
  17. data/lib/aspera/cli/formater.rb +105 -111
  18. data/lib/aspera/cli/info.rb +3 -2
  19. data/lib/aspera/cli/listener/line_dump.rb +1 -0
  20. data/lib/aspera/cli/listener/logger.rb +1 -0
  21. data/lib/aspera/cli/listener/progress.rb +13 -12
  22. data/lib/aspera/cli/listener/progress_multi.rb +21 -20
  23. data/lib/aspera/cli/main.rb +110 -90
  24. data/lib/aspera/cli/manager.rb +99 -88
  25. data/lib/aspera/cli/plugin.rb +98 -39
  26. data/lib/aspera/cli/plugins/alee.rb +6 -5
  27. data/lib/aspera/cli/plugins/aoc.rb +581 -450
  28. data/lib/aspera/cli/plugins/ats.rb +84 -83
  29. data/lib/aspera/cli/plugins/bss.rb +30 -27
  30. data/lib/aspera/cli/plugins/config.rb +488 -397
  31. data/lib/aspera/cli/plugins/console.rb +17 -15
  32. data/lib/aspera/cli/plugins/cos.rb +26 -35
  33. data/lib/aspera/cli/plugins/faspex.rb +206 -172
  34. data/lib/aspera/cli/plugins/faspex5.rb +109 -74
  35. data/lib/aspera/cli/plugins/node.rb +379 -189
  36. data/lib/aspera/cli/plugins/orchestrator.rb +71 -65
  37. data/lib/aspera/cli/plugins/preview.rb +131 -122
  38. data/lib/aspera/cli/plugins/server.rb +50 -150
  39. data/lib/aspera/cli/plugins/shares.rb +61 -27
  40. data/lib/aspera/cli/plugins/sync.rb +15 -14
  41. data/lib/aspera/cli/transfer_agent.rb +75 -64
  42. data/lib/aspera/cli/version.rb +2 -1
  43. data/lib/aspera/colors.rb +29 -28
  44. data/lib/aspera/command_line_builder.rb +50 -43
  45. data/lib/aspera/cos_node.rb +64 -38
  46. data/lib/aspera/data_repository.rb +1 -0
  47. data/lib/aspera/environment.rb +33 -10
  48. data/lib/aspera/fasp/agent_base.rb +35 -30
  49. data/lib/aspera/fasp/agent_connect.rb +35 -30
  50. data/lib/aspera/fasp/agent_direct.rb +68 -60
  51. data/lib/aspera/fasp/agent_httpgw.rb +71 -64
  52. data/lib/aspera/fasp/agent_node.rb +24 -23
  53. data/lib/aspera/fasp/agent_trsdk.rb +19 -20
  54. data/lib/aspera/fasp/error.rb +2 -1
  55. data/lib/aspera/fasp/error_info.rb +79 -68
  56. data/lib/aspera/fasp/installation.rb +130 -126
  57. data/lib/aspera/fasp/listener.rb +1 -0
  58. data/lib/aspera/fasp/parameters.rb +71 -60
  59. data/lib/aspera/fasp/parameters.yaml +69 -17
  60. data/lib/aspera/fasp/resume_policy.rb +14 -11
  61. data/lib/aspera/fasp/transfer_spec.rb +6 -5
  62. data/lib/aspera/fasp/uri.rb +25 -24
  63. data/lib/aspera/faspex_gw.rb +83 -72
  64. data/lib/aspera/hash_ext.rb +23 -13
  65. data/lib/aspera/id_generator.rb +16 -13
  66. data/lib/aspera/keychain/encrypted_hash.rb +61 -46
  67. data/lib/aspera/keychain/macos_security.rb +26 -24
  68. data/lib/aspera/log.rb +35 -39
  69. data/lib/aspera/nagios.rb +36 -28
  70. data/lib/aspera/node.rb +19 -19
  71. data/lib/aspera/oauth.rb +120 -100
  72. data/lib/aspera/open_application.rb +25 -22
  73. data/lib/aspera/persistency_action_once.rb +9 -8
  74. data/lib/aspera/persistency_folder.rb +13 -9
  75. data/lib/aspera/preview/file_types.rb +261 -266
  76. data/lib/aspera/preview/generator.rb +74 -73
  77. data/lib/aspera/preview/image_error.png +0 -0
  78. data/lib/aspera/preview/options.rb +7 -6
  79. data/lib/aspera/preview/utils.rb +30 -33
  80. data/lib/aspera/preview/video_error.png +0 -0
  81. data/lib/aspera/proxy_auto_config.rb +27 -23
  82. data/lib/aspera/rest.rb +73 -74
  83. data/lib/aspera/rest_call_error.rb +1 -0
  84. data/lib/aspera/rest_error_analyzer.rb +23 -19
  85. data/lib/aspera/rest_errors_aspera.rb +43 -40
  86. data/lib/aspera/secret_hider.rb +74 -0
  87. data/lib/aspera/ssh.rb +13 -10
  88. data/lib/aspera/sync.rb +49 -47
  89. data/lib/aspera/temp_file_manager.rb +7 -5
  90. data/lib/aspera/timer_limiter.rb +9 -8
  91. data/lib/aspera/uri_reader.rb +17 -18
  92. data/lib/aspera/web_auth.rb +17 -15
  93. data.tar.gz.sig +5 -0
  94. metadata +119 -35
  95. metadata.gz.sig +0 -0
  96. data/bin/dascli +0 -13
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'aspera/log'
3
4
  require 'aspera/command_line_builder'
4
5
  require 'aspera/temp_file_manager'
@@ -14,40 +15,45 @@ module Aspera
14
15
  # translate transfer specification to ascp parameter list
15
16
  class Parameters
16
17
  # Agents shown in manual for parameters (sub list)
17
- SUPPORTED_AGENTS=[:direct,:node,:connect]
18
+ SUPPORTED_AGENTS = %i[direct node connect].freeze
18
19
  # Short names of columns in manual
19
- SUPPORTED_AGENTS_SHORT=SUPPORTED_AGENTS.map{|a|a.to_s[0].to_sym}
20
+ SUPPORTED_AGENTS_SHORT = SUPPORTED_AGENTS.map{|a|a.to_s[0].to_sym}
21
+
22
+ private_constant :SUPPORTED_AGENTS
20
23
 
21
24
  class << self
22
25
  # Temp folder for file lists, must contain only file lists
23
26
  # because of garbage collection takes any file there
24
27
  # this could be refined, as , for instance, on macos, temp folder is already user specific
25
- @file_list_folder=TempFileManager.instance.new_file_path_global('asession_filelists')
26
- @param_description_cache=nil
28
+ @file_list_folder = TempFileManager.instance.new_file_path_global('asession_filelists')
29
+ @param_description_cache = nil
27
30
  # @return normalized description of transfer spec parameters, direct from yaml
28
31
  def description
29
- return @param_description_cache unless @param_description_cache.nil?
30
- # config file in same folder with same name as this source
31
- @param_description_cache=YAML.load_file("#{__FILE__[0..-3]}yaml")
32
- Aspera::CommandLineBuilder.normalize_description(@param_description_cache)
32
+ if @param_description_cache.nil?
33
+ # config file in same folder with same name as this source
34
+ description_from_yaml=YAML.load_file("#{__FILE__[0..-3]}yaml")
35
+ @param_description_cache = Aspera::CommandLineBuilder.normalize_description(description_from_yaml)
36
+ end
37
+ return @param_description_cache
33
38
  end
34
39
 
35
40
  # @return a table suitable to display in manual
36
41
  def man_table
37
- result=[]
42
+ result = []
38
43
  description.each do |k,i|
39
- param={name: k, type: [i[:accepted_types]].flatten.join(','),description: i[:desc]}
44
+ param = {name: k, type: [i[:accepted_types]].flatten.join(','),description: i[:desc]}
45
+ # add flags for supported agents in doc
40
46
  SUPPORTED_AGENTS.each do |a|
41
- param[a.to_s[0].to_sym]=i[:tragents].nil? || i[:tragents].include?(a) ? 'Y' : ''
47
+ param[a.to_s[0].to_sym] = i[:tragents].nil? || i[:tragents].include?(a) ? 'Y' : ''
42
48
  end
43
49
  # only keep lines that are usable in supported agents
44
50
  next if SUPPORTED_AGENTS_SHORT.inject(true){|m,j|m && param[j].empty?}
45
- param[:cli]=
46
- case i[:cltype]
47
- when :envvar then 'env:'+i[:clvarname]
48
- when :opt_without_arg,:opt_with_arg then i[:clswitch]
49
- else ''
50
- end
51
+ param[:cli] =
52
+ case i[:cltype]
53
+ when :envvar then 'env:' + i[:clvarname]
54
+ when :opt_without_arg,:opt_with_arg then i[:clswitch]
55
+ else ''
56
+ end
51
57
  if i.has_key?(:enum)
52
58
  param[:description] += "\nAllowed values: #{i[:enum].join(', ')}"
53
59
  end
@@ -65,17 +71,20 @@ module Aspera
65
71
  # special encoding methods used in YAML (key: :clconvert)
66
72
  def clconv_base64(v); Base64.strict_encode64(v); end
67
73
 
68
- def ts_has_file_list(ts)
69
- ts.has_key?('EX_ascp_args') and ts['EX_ascp_args'].is_a?(Array) and ['--file-list','--file-pair-list'].any?{|i|ts['EX_ascp_args'].include?(i)}
74
+ # file list is provided directly with ascp arguments
75
+ def ts_has_ascp_file_list(ts)
76
+ (ts['EX_ascp_args'].is_a?(Array) && ['--file-list','--file-pair-list'].any?{|i|ts['EX_ascp_args'].include?(i)}) ||
77
+ ts.has_key?('EX_file_list') ||
78
+ ts.has_key?('EX_file_pair_list')
70
79
  end
71
80
 
72
81
  def ts_to_env_args(transfer_spec,options)
73
- return Parameters.new(transfer_spec,options).ascp_args()
82
+ return Parameters.new(transfer_spec,options).ascp_args
74
83
  end
75
84
 
76
85
  # temp file list files are created here
77
86
  def file_list_folder=(v)
78
- @file_list_folder=v
87
+ @file_list_folder = v
79
88
  return if @file_list_folder.nil?
80
89
  FileUtils.mkdir_p(@file_list_folder)
81
90
  TempFileManager.instance.cleanup_expired(@file_list_folder)
@@ -87,18 +96,18 @@ module Aspera
87
96
 
88
97
  # @param options [Hash] key: :wss: bool
89
98
  def initialize(job_spec,options)
90
- @job_spec=job_spec
91
- @options=options
92
- @builder=Aspera::CommandLineBuilder.new(@job_spec,self.class.description)
99
+ @job_spec = job_spec
100
+ @options = options
101
+ @builder = Aspera::CommandLineBuilder.new(@job_spec,self.class.description)
93
102
  Log.log.debug("agent options: #{@options}")
94
103
  end
95
104
 
96
105
  # translate transfer spec to env vars and command line arguments for ascp
97
106
  # NOTE: parameters starting with "EX_" (extended) are not standard
98
107
  def ascp_args
99
- env_args={
100
- args: [],
101
- env: {},
108
+ env_args = {
109
+ args: [],
110
+ env: {},
102
111
  ascp_version: :ascp
103
112
  }
104
113
  # some ssh credentials are required to avoid interactive password input
@@ -117,12 +126,12 @@ module Aspera
117
126
  @builder.add_command_line_options(['--ws-connect'])
118
127
  # TODO: option to give order ssh,ws (legacy http is implied bu ssh)
119
128
  # quel bordel:
120
- @job_spec['ssh_port']=@builder.process_param('wss_port',:get_value)
129
+ @job_spec['ssh_port'] = @builder.process_param('wss_port',:get_value)
121
130
  @job_spec.delete('fasp_port')
122
131
  @job_spec.delete('EX_ssh_key_paths')
123
132
  @job_spec.delete('sshfp')
124
133
  # set location for CA bundle to be the one of Ruby, see env var SSL_CERT_FILE / SSL_CERT_DIR
125
- @job_spec['EX_ssh_key_paths']=[OpenSSL::X509::DEFAULT_CERT_FILE]
134
+ @job_spec['EX_ssh_key_paths'] = [OpenSSL::X509::DEFAULT_CERT_FILE]
126
135
  Log.log.debug('CA certs: EX_ssh_key_paths <- DEFAULT_CERT_FILE from openssl')
127
136
  else
128
137
  # remove unused parameter (avoid warning)
@@ -140,48 +149,50 @@ module Aspera
140
149
  # destination will be base64 encoded, put before path arguments
141
150
  @builder.add_command_line_options(['--dest64'])
142
151
  end
143
- # paths is mandatory, unless ...
144
- file_list_provided=self.class.ts_has_file_list(@job_spec)
145
- @builder.params_definition['paths'][:mandatory]=!@job_spec.has_key?('keepalive') and !file_list_provided
146
- paths_array=@builder.process_param('paths',:get_value)
147
- if file_list_provided && !paths_array.nil?
148
- Log.log.warn('file list provided both in transfer spec and ascp file list. Keeping file list only.')
149
- paths_array=nil
150
- end
151
- if !paths_array.nil?
152
- # it's an array
153
- raise 'paths is empty in transfer spec' if paths_array.empty?
154
- # use file list if there is storage defined for it.
155
- if self.class.file_list_folder.nil?
156
- # not safe for special characters ? (maybe not, depends on OS)
157
- Log.log.debug('placing source file list on command line (no file list file)')
158
- @builder.add_command_line_options(paths_array.map{|i|i['source']})
152
+ # process file lists
153
+ begin
154
+ # is the file list provided through EX_ parameters?
155
+ ascp_file_list_provided = self.class.ts_has_ascp_file_list(@job_spec)
156
+ # set if paths is mandatory in ts
157
+ @builder.params_definition['paths'][:mandatory] = !@job_spec.has_key?('keepalive') && !ascp_file_list_provided
158
+ # get paths in transfer spec (after setting if it is mandatory)
159
+ ts_paths_array = @builder.process_param('paths',:get_value)
160
+ if ascp_file_list_provided && !ts_paths_array.nil?
161
+ raise 'file list provided both in transfer spec and ascp file list. Remove one of them.'
162
+ end
163
+ # option 1: EX_file_list
164
+ file_list_file = @builder.process_param('EX_file_list',:get_value)
165
+ if !file_list_file.nil?
166
+ option = '--file-list'
159
167
  else
160
- file_list_file=@builder.process_param('EX_file_list',:get_value)
168
+ # option 2: EX_file_pair_list
169
+ file_list_file = @builder.process_param('EX_file_pair_list',:get_value)
161
170
  if !file_list_file.nil?
162
- option='--file-list'
163
- else
164
- file_list_file=@builder.process_param('EX_file_pair_list',:get_value)
165
- if !file_list_file.nil?
166
- option='--file-pair-list'
167
- else
168
- # safer option: file list
171
+ option = '--file-pair-list'
172
+ elsif !ts_paths_array.nil?
173
+ # option 3: in TS, it is an array
174
+ if !self.class.file_list_folder.nil?
175
+ # safer option: generate a file list file if there is storage defined for it
169
176
  # if there is destination in paths, then use filepairlist
170
177
  # TODO: well, we test only the first one, but anyway it shall be consistent
171
- if paths_array.first.has_key?('destination')
172
- option='--file-pair-list'
173
- lines=paths_array.each_with_object([]){|e,m|m.push(e['source'],e['destination']);}
178
+ if ts_paths_array.first.has_key?('destination')
179
+ option = '--file-pair-list'
180
+ lines = ts_paths_array.each_with_object([]){|e,m|m.push(e['source'],e['destination']);}
174
181
  else
175
- option='--file-list'
176
- lines=paths_array.map{|i|i['source']}
182
+ option = '--file-list'
183
+ lines = ts_paths_array.map{|i|i['source']}
177
184
  end
178
- file_list_file=Aspera::TempFileManager.instance.new_file_path_in_folder(self.class.file_list_folder)
185
+ file_list_file = Aspera::TempFileManager.instance.new_file_path_in_folder(self.class.file_list_folder)
179
186
  File.write(file_list_file, lines.join("\n"))
180
187
  Log.log.debug{"#{option}=\n#{File.read(file_list_file)}".red}
188
+ else
189
+ # not safe for special characters ? (maybe not, depends on OS)
190
+ Log.log.debug('placing source file list on command line (no file list file)')
191
+ @builder.add_command_line_options(ts_paths_array.map{|i|i['source']})
181
192
  end
182
193
  end
183
- @builder.add_command_line_options(["#{option}=#{file_list_file}"])
184
194
  end
195
+ @builder.add_command_line_options(["#{option}=#{file_list_file}"]) unless option.nil?
185
196
  end
186
197
  # optional args, at the end to override previous ones (to allow override)
187
198
  @builder.add_command_line_options(@builder.process_param('EX_ascp_args',:get_value))
@@ -49,7 +49,13 @@ create_dir:
49
49
  :cltype: :opt_without_arg
50
50
  :clswitch: "-d"
51
51
  delete_before_transfer:
52
- :desc: "Before transfer, delete files that exist at the destination but not at the source. The source and destination arguments must be directories that have matching names. Objects on the destination that have the same name but different type or size as objects on the source are not deleted."
52
+ :desc: |-
53
+ Before transfer, delete files that exist at the destination but not at the source.
54
+ The source and destination arguments must be directories that have matching names.
55
+ Objects on the destination that have the same name but different type or size as objects
56
+ on the source are not deleted.
57
+
58
+
53
59
  :cltype: :opt_without_arg
54
60
  delete_source: # duplicate of remove_after_transfer ?
55
61
  :desc: Remove SRC files after transfer success
@@ -138,16 +144,24 @@ https_fallback_port:
138
144
  :cltype: :opt_with_arg
139
145
  :clswitch: "-t"
140
146
  move_after_transfer:
147
+ :desc: The relative path to which the files will be moved after the transfer at the source side.
141
148
  :cltype: :opt_with_arg
142
149
  multi_session:
143
- :desc: "Use multi-session transfer. max 128.\n
144
- Each participant on one host needs an independent UDP (-O) port.\n
145
- Large files are split between sessions only when transferring with resume_policy=none."
150
+ :desc: |
151
+ Use multi-session transfer. max 128.
152
+ Each participant on one host needs an independent UDP (-O) port.
153
+ Large files are split between sessions only when transferring with resume_policy=none.
154
+
155
+
146
156
  :accepted_types: :int
147
157
  :cltype: :ignore
148
158
  :clswitch: "-C"
149
159
  multi_session_threshold:
150
- :desc: Split files across multiple ascp sessions if their size in bytes is greater than or equal to the specified value. (0=no file is split)
160
+ :desc: |-
161
+ Split files across multiple ascp sessions if their size in bytes is greater than or equal to the specified value.
162
+ (0=no file is split)
163
+
164
+
151
165
  :accepted_types: :int
152
166
  :tragents:
153
167
  - :direct
@@ -163,6 +177,18 @@ overwrite:
163
177
  - older
164
178
  - diff+older
165
179
  :cltype: :opt_with_arg
180
+ password:
181
+ :desc: |-
182
+ Password for local Windows user when transfer user associated with node api user is not the same as the one running asperanoded.
183
+ Allows impersonating the transfer user and have access to resources (e.g. network shares).
184
+ Windows only, node api only.
185
+
186
+
187
+ :required: false
188
+ :accepted_types: :string
189
+ :cltype: :ignore
190
+ :tragents:
191
+ - :node
166
192
  paths:
167
193
  :desc: Array of path to the source (required) and a path to the destination (optional).
168
194
  :required: true
@@ -233,10 +259,13 @@ remove_skipped:
233
259
  - :node
234
260
  :cltype: :opt_without_arg
235
261
  proxy:
236
- :desc: "Specify the address of the Aspera high-speed proxy server.\n
237
- dnat(s)://[user[:password]@]server:port\n
238
- Default ports for DNAT and DNATS protocols are 9091 and 9092.\n
239
- Password, if specified here, overrides the value of environment variable ASPERA_PROXY_PASS."
262
+ :desc: |-
263
+ Specify the address of the Aspera high-speed proxy server.
264
+ dnat(s)://[user[:password]@]server:port
265
+ Default ports for DNAT and DNATS protocols are 9091 and 9092.
266
+ Password, if specified here, overrides the value of environment variable ASPERA_PROXY_PASS.
267
+
268
+
240
269
  :tragents:
241
270
  - :direct
242
271
  - :sdk
@@ -279,9 +308,12 @@ ssh_port:
279
308
  :cltype: :opt_with_arg
280
309
  :clswitch: "-P"
281
310
  ssh_private_key:
282
- :desc: "Private key used for SSH authentication.\n
283
- Shall look like: -----BEGIN RSA PRIV4TE KEY-----\\nMII...\n
284
- Note the JSON encoding: \\n for newlines."
311
+ :desc: |-
312
+ Private key used for SSH authentication.
313
+ Shall look like: -----BEGIN RSA PRIV4TE KEY-----\nMII...
314
+ Note the JSON encoding: \n for newlines.
315
+
316
+
285
317
  :tragents:
286
318
  - :direct
287
319
  - :sdk
@@ -355,8 +387,11 @@ use_system_ssh:
355
387
  :cltype: :ignore
356
388
  :clswitch: "-SSH"
357
389
  source_root:
358
- :desc: "Path to be prepended to each source path.\n
359
- This is either a conventional path or it can be a URI but only if there is no root defined."
390
+ :desc: |-
391
+ Path to be prepended to each source path.
392
+ This is either a conventional path or it can be a URI but only if there is no root defined.
393
+
394
+
360
395
  :cltype: :opt_with_arg
361
396
  :clswitch: "--source-prefix64"
362
397
  :clconvert: Aspera::Fasp::Parameters.clconv_base64
@@ -377,6 +412,20 @@ apply_local_docroot:
377
412
  - :direct
378
413
  - :sdk
379
414
  :cltype: :opt_without_arg
415
+ src_base:
416
+ :desc: |-
417
+ Specify the prefix to be stripped off from each source object.
418
+ The remaining portion of the source path is kept intact at the destination.
419
+ Special care must be taken when used with cloud storage.
420
+
421
+
422
+ :tragents:
423
+ - :direct
424
+ - :node
425
+ - :sdk
426
+ :cltype: :opt_with_arg
427
+ :clswitch: "--src-base64"
428
+ :clconvert: Aspera::Fasp::Parameters.clconv_base64
380
429
  preserve_acls:
381
430
  :desc: "Preserve access control lists."
382
431
  :enum:
@@ -440,14 +489,17 @@ remove_empty_source_directory:
440
489
  - :sdk
441
490
  :cltype: :opt_without_arg
442
491
  EX_at_rest_password:
443
- :desc: "Passphrase used for at rest encryption or decryption. Prefer to use standard: content_protection_password"
492
+ :desc: "DEPRECATED: Prefer to use standard parameter: content_protection_password"
444
493
  :tragents:
445
494
  - :direct
446
495
  :cltype: :envvar
447
496
  :clvarname: ASPERA_SCP_FILEPASS
448
497
  EX_proxy_password:
449
- :desc: "Password used for Aspera proxy server authentication.\n
450
- May be overridden by password in URL EX_fasp_proxy_url."
498
+ :desc: |-
499
+ Password used for Aspera proxy server authentication.
500
+ May be overridden by password in URL EX_fasp_proxy_url.
501
+
502
+
451
503
  :tragents:
452
504
  - :direct
453
505
  :cltype: :envvar
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'singleton'
3
4
  require 'aspera/log'
4
5
 
@@ -7,22 +8,22 @@ module Aspera
7
8
  # implements a simple resume policy
8
9
  class ResumePolicy
9
10
  # list of supported parameters and default values
10
- DEFAULTS={
11
- iter_max: 7,
12
- sleep_initial: 2,
13
- sleep_factor: 2,
14
- sleep_max: 60
15
- }
11
+ DEFAULTS = {
12
+ iter_max: 7,
13
+ sleep_initial: 2,
14
+ sleep_factor: 2,
15
+ sleep_max: 60
16
+ }.freeze
16
17
 
17
18
  # @param params see DEFAULTS
18
19
  def initialize(params=nil)
19
- @parameters=DEFAULTS.clone
20
+ @parameters = DEFAULTS.dup
20
21
  if !params.nil?
21
22
  raise "expecting Hash (or nil), but have #{params.class}" unless params.is_a?(Hash)
22
23
  params.each do |k,v|
23
24
  raise "unknown resume parameter: #{k}, expect one of #{DEFAULTS.keys.map(&:to_s).join(',')}" unless DEFAULTS.has_key?(k)
24
25
  raise "#{k} must be Integer" unless v.is_a?(Integer)
25
- @parameters[k]=v
26
+ @parameters[k] = v
26
27
  end
27
28
  end
28
29
  Log.log.debug("resume params=#{@parameters}")
@@ -30,7 +31,8 @@ module Aspera
30
31
 
31
32
  # calls block a number of times (resumes) until success or limit reached
32
33
  # this is re-entrant, one resumer can handle multiple transfers in //
33
- def process(&block)
34
+ def execute_with_resume
35
+ raise 'block manndatory' unless block_given?
34
36
  # maximum of retry
35
37
  remaining_resumes = @parameters[:iter_max]
36
38
  sleep_seconds = @parameters[:sleep_initial]
@@ -39,7 +41,8 @@ module Aspera
39
41
  loop do
40
42
  Log.log.debug('transfer starting');
41
43
  begin
42
- block.call
44
+ # call provided block
45
+ yield
43
46
  break
44
47
  rescue Fasp::Error => e
45
48
  Log.log.warn("An error occured: #{e.message}");
@@ -57,7 +60,7 @@ module Aspera
57
60
  end
58
61
 
59
62
  # take this retry in account
60
- remaining_resumes-=1
63
+ remaining_resumes -= 1
61
64
  Log.log.warn("resuming in #{sleep_seconds} seconds (retry left:#{remaining_resumes})");
62
65
 
63
66
  # wait a bit before retrying, maybe network condition will be better
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'aspera/fasp/parameters'
3
4
 
4
5
  module Aspera
@@ -6,14 +7,14 @@ module Aspera
6
7
  # parameters for Transfer Spec
7
8
  class TransferSpec
8
9
  # default transfer username for access key based transfers
9
- ACCESS_KEY_TRANSFER_USER='xfer'
10
- SSH_PORT=33_001
11
- UDP_PORT=33_001
12
- AK_TSPEC_BASE={
10
+ ACCESS_KEY_TRANSFER_USER = 'xfer'
11
+ SSH_PORT = 33_001
12
+ UDP_PORT = 33_001
13
+ AK_TSPEC_BASE = {
13
14
  'remote_user' => ACCESS_KEY_TRANSFER_USER,
14
15
  'ssh_port' => SSH_PORT,
15
16
  'fasp_port' => UDP_PORT
16
- }
17
+ }.freeze
17
18
  # define constants for enums of parameters: <paramater>_<enum>, e.g. CIPHER_AES_128
18
19
  Aspera::Fasp::Parameters.description.each do |k,v|
19
20
  next unless v[:enum].is_a?(Array)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'aspera/log'
3
4
  require 'aspera/command_line_builder'
4
5
 
@@ -7,38 +8,38 @@ module Aspera
7
8
  # translates a "faspe:" URI (used in Faspex) into transfer spec hash
8
9
  class Uri
9
10
  def initialize(fasplink)
10
- @fasp_uri=URI.parse(fasplink.gsub(' ','%20'))
11
+ @fasp_uri = URI.parse(fasplink.gsub(' ','%20'))
11
12
  # TODO: check scheme is faspe
12
13
  end
13
14
 
14
15
  def transfer_spec
15
- result_ts={}
16
- result_ts['remote_host']=@fasp_uri.host
17
- result_ts['remote_user']=@fasp_uri.user
18
- result_ts['ssh_port']=@fasp_uri.port
19
- result_ts['paths']=[{'source'=>URI.decode_www_form_component(@fasp_uri.path)}]
16
+ result_ts = {}
17
+ result_ts['remote_host'] = @fasp_uri.host
18
+ result_ts['remote_user'] = @fasp_uri.user
19
+ result_ts['ssh_port'] = @fasp_uri.port
20
+ result_ts['paths'] = [{'source' => URI.decode_www_form_component(@fasp_uri.path)}]
20
21
  # faspex does not encode trailing base64 encoded tags, fix that
21
- fixed_query = @fasp_uri.query.gsub(/(=+)$/){|x|'%3D'*x.length}
22
+ fixed_query = @fasp_uri.query.gsub(/(=+)$/){|x|'%3D' * x.length}
22
23
 
23
24
  URI.decode_www_form(fixed_query).each do |i|
24
- name=i[0]
25
- value=i[1]
25
+ name = i[0]
26
+ value = i[1]
26
27
  case name
27
- when 'cookie' then result_ts['cookie']=value
28
- when 'token' then result_ts['token']=value
29
- when 'sshfp' then result_ts['sshfp']=value
30
- when 'policy' then result_ts['rate_policy']=value
31
- when 'httpport' then result_ts['http_fallback_port']=value.to_i
32
- when 'targetrate' then result_ts['target_rate_kbps']=value.to_i
33
- when 'minrate' then result_ts['min_rate_kbps']=value.to_i
34
- when 'port' then result_ts['fasp_port']=value.to_i
35
- when 'bwcap' then result_ts['target_rate_cap_kbps']=value.to_i
36
- when 'enc' then result_ts['cipher']=value.gsub(/^aes/,'aes-').gsub(/cfb$/,'-cfb').gsub(/gcm$/,'-gcm').gsub(/--/,'-')
37
- when 'tags64' then result_ts['tags']=JSON.parse(Base64.strict_decode64(value))
38
- when 'createpath' then result_ts['create_dir']=CommandLineBuilder.yes_to_true(value)
39
- when 'fallback' then result_ts['http_fallback']=CommandLineBuilder.yes_to_true(value)
40
- when 'lockpolicy' then result_ts['lock_rate_policy']=CommandLineBuilder.yes_to_true(value)
41
- when 'lockminrate' then result_ts['lock_min_rate']=CommandLineBuilder.yes_to_true(value)
28
+ when 'cookie' then result_ts['cookie'] = value
29
+ when 'token' then result_ts['token'] = value
30
+ when 'sshfp' then result_ts['sshfp'] = value
31
+ when 'policy' then result_ts['rate_policy'] = value
32
+ when 'httpport' then result_ts['http_fallback_port'] = value.to_i
33
+ when 'targetrate' then result_ts['target_rate_kbps'] = value.to_i
34
+ when 'minrate' then result_ts['min_rate_kbps'] = value.to_i
35
+ when 'port' then result_ts['fasp_port'] = value.to_i
36
+ when 'bwcap' then result_ts['target_rate_cap_kbps'] = value.to_i
37
+ when 'enc' then result_ts['cipher'] = value.gsub(/^aes/,'aes-').gsub(/cfb$/,'-cfb').gsub(/gcm$/,'-gcm').gsub(/--/,'-')
38
+ when 'tags64' then result_ts['tags'] = JSON.parse(Base64.strict_decode64(value))
39
+ when 'createpath' then result_ts['create_dir'] = CommandLineBuilder.yes_to_true(value)
40
+ when 'fallback' then result_ts['http_fallback'] = CommandLineBuilder.yes_to_true(value)
41
+ when 'lockpolicy' then result_ts['lock_rate_policy'] = CommandLineBuilder.yes_to_true(value)
42
+ when 'lockminrate' then result_ts['lock_min_rate'] = CommandLineBuilder.yes_to_true(value)
42
43
  when 'auth' then Log.log.debug("ignoring auth #{name}=#{value}") # TODO: translate into transfer spec ? yes/no
43
44
  when 'v' then Log.log.debug("ignoring v #{name}=#{value}") # TODO: translate into transfer spec ? 2
44
45
  when 'protect' then Log.log.debug("ignoring protect #{name}=#{value}") # TODO: translate into transfer spec ?