aspera-cli 4.10.0 → 4.12.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 (97) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/BUGS.md +19 -0
  4. data/CHANGELOG.md +528 -0
  5. data/CONTRIBUTING.md +143 -0
  6. data/README.md +977 -589
  7. data/bin/ascli +4 -4
  8. data/bin/asession +12 -12
  9. data/docs/test_env.conf +29 -19
  10. data/examples/aoc.rb +6 -6
  11. data/examples/dascli +18 -16
  12. data/examples/faspex4.rb +15 -15
  13. data/examples/node.rb +12 -12
  14. data/examples/proxy.pac +2 -2
  15. data/examples/server.rb +12 -12
  16. data/lib/aspera/aoc.rb +344 -272
  17. data/lib/aspera/ascmd.rb +56 -54
  18. data/lib/aspera/ats_api.rb +4 -4
  19. data/lib/aspera/cli/basic_auth_plugin.rb +15 -12
  20. data/lib/aspera/cli/extended_value.rb +9 -9
  21. data/lib/aspera/cli/{formater.rb → formatter.rb} +69 -69
  22. data/lib/aspera/cli/listener/line_dump.rb +1 -1
  23. data/lib/aspera/cli/listener/logger.rb +1 -1
  24. data/lib/aspera/cli/listener/progress.rb +5 -6
  25. data/lib/aspera/cli/listener/progress_multi.rb +16 -21
  26. data/lib/aspera/cli/main.rb +72 -73
  27. data/lib/aspera/cli/manager.rb +112 -112
  28. data/lib/aspera/cli/plugin.rb +68 -48
  29. data/lib/aspera/cli/plugins/alee.rb +4 -4
  30. data/lib/aspera/cli/plugins/aoc.rb +322 -720
  31. data/lib/aspera/cli/plugins/ats.rb +50 -52
  32. data/lib/aspera/cli/plugins/bss.rb +10 -10
  33. data/lib/aspera/cli/plugins/config.rb +514 -410
  34. data/lib/aspera/cli/plugins/console.rb +12 -12
  35. data/lib/aspera/cli/plugins/cos.rb +18 -20
  36. data/lib/aspera/cli/plugins/faspex.rb +134 -136
  37. data/lib/aspera/cli/plugins/faspex5.rb +235 -70
  38. data/lib/aspera/cli/plugins/node.rb +378 -309
  39. data/lib/aspera/cli/plugins/orchestrator.rb +52 -49
  40. data/lib/aspera/cli/plugins/preview.rb +129 -120
  41. data/lib/aspera/cli/plugins/server.rb +137 -83
  42. data/lib/aspera/cli/plugins/shares.rb +77 -52
  43. data/lib/aspera/cli/plugins/sync.rb +13 -33
  44. data/lib/aspera/cli/transfer_agent.rb +61 -61
  45. data/lib/aspera/cli/version.rb +2 -1
  46. data/lib/aspera/colors.rb +3 -3
  47. data/lib/aspera/command_line_builder.rb +78 -74
  48. data/lib/aspera/cos_node.rb +31 -29
  49. data/lib/aspera/data_repository.rb +1 -1
  50. data/lib/aspera/environment.rb +30 -28
  51. data/lib/aspera/fasp/agent_base.rb +17 -15
  52. data/lib/aspera/fasp/agent_connect.rb +34 -32
  53. data/lib/aspera/fasp/agent_direct.rb +70 -73
  54. data/lib/aspera/fasp/agent_httpgw.rb +79 -74
  55. data/lib/aspera/fasp/agent_node.rb +26 -26
  56. data/lib/aspera/fasp/agent_trsdk.rb +20 -20
  57. data/lib/aspera/fasp/error.rb +3 -2
  58. data/lib/aspera/fasp/error_info.rb +11 -8
  59. data/lib/aspera/fasp/installation.rb +80 -80
  60. data/lib/aspera/fasp/listener.rb +2 -2
  61. data/lib/aspera/fasp/parameters.rb +103 -92
  62. data/lib/aspera/fasp/parameters.yaml +313 -214
  63. data/lib/aspera/fasp/resume_policy.rb +10 -10
  64. data/lib/aspera/fasp/transfer_spec.rb +22 -2
  65. data/lib/aspera/fasp/uri.rb +7 -7
  66. data/lib/aspera/faspex_gw.rb +80 -159
  67. data/lib/aspera/faspex_postproc.rb +77 -0
  68. data/lib/aspera/hash_ext.rb +3 -3
  69. data/lib/aspera/id_generator.rb +5 -5
  70. data/lib/aspera/keychain/encrypted_hash.rb +23 -28
  71. data/lib/aspera/keychain/macos_security.rb +21 -20
  72. data/lib/aspera/log.rb +13 -13
  73. data/lib/aspera/nagios.rb +24 -23
  74. data/lib/aspera/node.rb +217 -38
  75. data/lib/aspera/oauth.rb +78 -74
  76. data/lib/aspera/open_application.rb +19 -11
  77. data/lib/aspera/persistency_action_once.rb +4 -4
  78. data/lib/aspera/persistency_folder.rb +13 -13
  79. data/lib/aspera/preview/file_types.rb +8 -8
  80. data/lib/aspera/preview/generator.rb +67 -67
  81. data/lib/aspera/preview/utils.rb +27 -27
  82. data/lib/aspera/proxy_auto_config.js +63 -63
  83. data/lib/aspera/proxy_auto_config.rb +19 -19
  84. data/lib/aspera/rest.rb +65 -67
  85. data/lib/aspera/rest_call_error.rb +2 -1
  86. data/lib/aspera/rest_error_analyzer.rb +22 -21
  87. data/lib/aspera/rest_errors_aspera.rb +16 -16
  88. data/lib/aspera/secret_hider.rb +17 -14
  89. data/lib/aspera/ssh.rb +15 -14
  90. data/lib/aspera/sync.rb +177 -62
  91. data/lib/aspera/temp_file_manager.rb +2 -2
  92. data/lib/aspera/uri_reader.rb +4 -4
  93. data/lib/aspera/web_auth.rb +13 -64
  94. data/lib/aspera/web_server_simple.rb +76 -0
  95. data.tar.gz.sig +0 -0
  96. metadata +11 -6
  97. metadata.gz.sig +0 -0
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Aspera
4
4
  module Fasp
5
- # imlement this class to get transfer events
6
- class Listener
5
+ # implement this class to get transfer events
6
+ class Listener # rubocop:disable Lint/EmptyClass
7
7
  # define one of the following methods:
8
8
  # event_text(text_data)
9
9
  # event_struct(legacy_names)
@@ -18,8 +18,9 @@ module Aspera
18
18
  SUPPORTED_AGENTS = %i[direct node connect].freeze
19
19
  # Short names of columns in manual
20
20
  SUPPORTED_AGENTS_SHORT = SUPPORTED_AGENTS.map{|a|a.to_s[0].to_sym}
21
+ FILE_LIST_OPTIONS = ['--file-list', '--file-pair-list'].freeze
21
22
 
22
- private_constant :SUPPORTED_AGENTS
23
+ private_constant :SUPPORTED_AGENTS, :FILE_LIST_OPTIONS
23
24
 
24
25
  class << self
25
26
  # Temp folder for file lists, must contain only file lists
@@ -31,67 +32,71 @@ module Aspera
31
32
  def description
32
33
  if @param_description_cache.nil?
33
34
  # config file in same folder with same name as this source
34
- description_from_yaml=YAML.load_file("#{__FILE__[0..-3]}yaml")
35
+ description_from_yaml = YAML.load_file("#{__FILE__[0..-3]}yaml")
35
36
  @param_description_cache = Aspera::CommandLineBuilder.normalize_description(description_from_yaml)
36
37
  end
37
38
  return @param_description_cache
38
39
  end
39
40
 
40
41
  # @return a table suitable to display in manual
41
- def man_table
42
+ def man_table(to_text: true)
42
43
  result = []
43
- description.each do |k,i|
44
- param = {name: k, type: [i[:accepted_types]].flatten.join(','),description: i[:desc]}
44
+ description.each do |name, options|
45
+ param = {name: name, type: [options[:accepted_types]].flatten.join(','), description: options[:desc]}
45
46
  # add flags for supported agents in doc
46
47
  SUPPORTED_AGENTS.each do |a|
47
- param[a.to_s[0].to_sym] = i[:tragents].nil? || i[:tragents].include?(a) ? 'Y' : ''
48
+ param[a.to_s[0].to_sym] = options[:agents].nil? || options[:agents].include?(a) ? 'Y' : ''
48
49
  end
49
50
  # only keep lines that are usable in supported agents
50
- next if SUPPORTED_AGENTS_SHORT.inject(true){|m,j|m && param[j].empty?}
51
+ next if SUPPORTED_AGENTS_SHORT.inject(true){|m, j|m && param[j].empty?}
51
52
  param[:cli] =
52
- case i[:cltype]
53
- when :envvar then 'env:' + i[:clvarname]
54
- when :opt_without_arg then i[:clswitch]
53
+ case options[:cli][:type]
54
+ when :envvar then 'env:' + options[:cli][:variable]
55
+ when :opt_without_arg then options[:cli][:switch]
55
56
  when :opt_with_arg
56
- values=if i.has_key?(:enum)
57
+ values = if options.key?(:enum)
57
58
  ['enum']
58
- elsif i[:accepted_types].is_a?(Array)
59
- i[:accepted_types]
60
- elsif !i[:accepted_types].nil?
61
- [i[:accepted_types]]
59
+ elsif options[:accepted_types].is_a?(Array)
60
+ options[:accepted_types]
61
+ elsif !options[:accepted_types].nil?
62
+ [options[:accepted_types]]
62
63
  else
63
64
  raise "error: #{param}"
64
65
  end.map{|n|"{#{n}}"}.join('|')
65
- conv=i.has_key?(:clconvert) ? '(conversion)' : ''
66
- "#{i[:clswitch]} #{conv}#{values}"
66
+ conv = options[:cli].key?(:convert) ? '(conversion)' : ''
67
+ "#{options[:cli][:switch]} #{conv}#{values}"
67
68
  else ''
68
69
  end
69
- if i.has_key?(:enum)
70
- param[:description] += "\nAllowed values: #{i[:enum].join(', ')}"
70
+ if options.key?(:enum)
71
+ param[:description] += "\nAllowed values: #{options[:enum].join(', ')}"
71
72
  end
73
+ param[:description] = param[:description].gsub('&sol;', '/') if to_text
72
74
  result.push(param)
73
75
  end
74
76
  return result
75
77
  end
76
78
 
77
- # special encoding methods used in YAML (key: :clconvert)
78
- def clconv_remove_hyphen(v); v.tr('-',''); end
79
+ # special encoding methods used in YAML (key: :convert)
80
+ def convert_remove_hyphen(v); v.tr('-', ''); end
79
81
 
80
- # special encoding methods used in YAML (key: :clconvert)
81
- def clconv_json64(v); Base64.strict_encode64(JSON.generate(v)); end
82
+ # special encoding methods used in YAML (key: :convert)
83
+ def convert_json64(v); Base64.strict_encode64(JSON.generate(v)); end
82
84
 
83
- # special encoding methods used in YAML (key: :clconvert)
84
- def clconv_base64(v); Base64.strict_encode64(v); end
85
+ # special encoding methods used in YAML (key: :convert)
86
+ def convert_base64(v); Base64.strict_encode64(v); end
85
87
 
86
88
  # file list is provided directly with ascp arguments
87
- def ts_has_ascp_file_list(ts)
88
- (ts['EX_ascp_args'].is_a?(Array) && ['--file-list','--file-pair-list'].any?{|i|ts['EX_ascp_args'].include?(i)}) ||
89
- ts.has_key?('EX_file_list') ||
90
- ts.has_key?('EX_file_pair_list')
89
+ def ts_has_ascp_file_list(ts, ascp_args)
90
+ # it can also be option transfer_info
91
+ ascp_args = ascp_args['ascp_args'] if ascp_args.is_a?(Hash)
92
+ (ts['EX_ascp_args'].is_a?(Array) && ts['EX_ascp_args'].any?{|i|FILE_LIST_OPTIONS.include?(i)}) ||
93
+ (ascp_args.is_a?(Array) && ascp_args.any?{|i|FILE_LIST_OPTIONS.include?(i)}) ||
94
+ ts.key?('EX_file_list') ||
95
+ ts.key?('EX_file_pair_list')
91
96
  end
92
97
 
93
- def ts_to_env_args(transfer_spec,options)
94
- return Parameters.new(transfer_spec,options).ascp_args
98
+ def ts_to_env_args(transfer_spec, wss:, ascp_args:)
99
+ return Parameters.new(transfer_spec, wss: wss, ascp_args: ascp_args).ascp_args
95
100
  end
96
101
 
97
102
  # temp file list files are created here
@@ -106,12 +111,60 @@ module Aspera
106
111
  attr_reader :file_list_folder
107
112
  end # self
108
113
 
109
- # @param options [Hash] key: :wss: bool
110
- def initialize(job_spec,options)
114
+ # @param options [Hash] key: :wss: bool, :ascp_args: array of strings
115
+ def initialize(job_spec, wss:, ascp_args:)
111
116
  @job_spec = job_spec
112
- @options = options
113
- @builder = Aspera::CommandLineBuilder.new(@job_spec,self.class.description)
114
- Log.log.debug("agent options: #{@options}")
117
+ @opt_wss = wss
118
+ @opt_args = ascp_args
119
+ Log.log.debug{"agent options: #{@opt_wss} #{@opt_args}"}
120
+ raise 'ascp args must be an Array' unless @opt_args.is_a?(Array)
121
+ raise 'ascp args must be an Array of String' if @opt_args.any?{|i|!i.is_a?(String)}
122
+ @builder = Aspera::CommandLineBuilder.new(@job_spec, self.class.description)
123
+ end
124
+
125
+ def process_file_list
126
+ # is the file list provided through EX_ parameters?
127
+ ascp_file_list_provided = self.class.ts_has_ascp_file_list(@job_spec, @opt_args)
128
+ # set if paths is mandatory in ts
129
+ @builder.params_definition['paths'][:mandatory] = !@job_spec.key?('keepalive') && !ascp_file_list_provided
130
+ # get paths in transfer spec (after setting if it is mandatory)
131
+ ts_paths_array = @builder.read_param('paths')
132
+ if ascp_file_list_provided && !ts_paths_array.nil?
133
+ raise 'file list provided both in transfer spec and ascp file list. Remove one of them.'
134
+ end
135
+ # option 1: EX_file_list
136
+ file_list_file = @builder.read_param('EX_file_list')
137
+ if file_list_file.nil?
138
+ # option 2: EX_file_pair_list
139
+ file_list_file = @builder.read_param('EX_file_pair_list')
140
+ if !file_list_file.nil?
141
+ option = '--file-pair-list'
142
+ elsif !ts_paths_array.nil?
143
+ # option 3: in TS, it is an array
144
+ if self.class.file_list_folder.nil?
145
+ # not safe for special characters ? (maybe not, depends on OS)
146
+ Log.log.debug('placing source file list on command line (no file list file)')
147
+ @builder.add_command_line_options(ts_paths_array.map{|i|i['source']})
148
+ else
149
+ # safer option: generate a file list file if there is storage defined for it
150
+ # if there is destination in paths, then use file-pair-list
151
+ # TODO: well, we test only the first one, but anyway it shall be consistent
152
+ if ts_paths_array.first.key?('destination')
153
+ option = '--file-pair-list'
154
+ lines = ts_paths_array.each_with_object([]){|e, m|m.push(e['source'], e['destination']); }
155
+ else
156
+ option = '--file-list'
157
+ lines = ts_paths_array.map{|i|i['source']}
158
+ end
159
+ file_list_file = Aspera::TempFileManager.instance.new_file_path_in_folder(self.class.file_list_folder)
160
+ File.write(file_list_file, lines.join("\n"))
161
+ Log.log.debug{"#{option}=\n#{File.read(file_list_file)}".red}
162
+ end
163
+ end
164
+ else
165
+ option = '--file-list'
166
+ end
167
+ @builder.add_command_line_options(["#{option}=#{file_list_file}"]) unless option.nil?
115
168
  end
116
169
 
117
170
  # translate transfer spec to env vars and command line arguments for ascp
@@ -123,22 +176,22 @@ module Aspera
123
176
  ascp_version: :ascp
124
177
  }
125
178
  # some ssh credentials are required to avoid interactive password input
126
- if !@job_spec.has_key?('remote_password') &&
127
- !@job_spec.has_key?('ssh_private_key') &&
128
- !@job_spec.has_key?('EX_ssh_key_paths')
179
+ if !@job_spec.key?('remote_password') &&
180
+ !@job_spec.key?('ssh_private_key') &&
181
+ !@job_spec.key?('EX_ssh_key_paths')
129
182
  raise Fasp::Error, 'required: password or ssh key (value or path)'
130
183
  end
131
184
 
132
185
  # special cases
133
- @job_spec.delete('source_root') if @job_spec.has_key?('source_root') && @job_spec['source_root'].empty?
186
+ @job_spec.delete('source_root') if @job_spec.key?('source_root') && @job_spec['source_root'].empty?
134
187
 
135
188
  # use web socket session initiation ?
136
- if @builder.process_param('wss_enabled',:get_value) && (@options[:wss] || !@job_spec.has_key?('fasp_port'))
189
+ if @builder.read_param('wss_enabled') && (@opt_wss || !@job_spec.key?('fasp_port'))
137
190
  # by default use web socket session if available, unless removed by user
138
191
  @builder.add_command_line_options(['--ws-connect'])
139
192
  # TODO: option to give order ssh,ws (legacy http is implied bu ssh)
140
- # quel bordel:
141
- @job_spec['ssh_port'] = @builder.process_param('wss_port',:get_value)
193
+ # This will need to be cleaned up in aspera core
194
+ @job_spec['ssh_port'] = @builder.read_param('wss_port')
142
195
  @job_spec.delete('fasp_port')
143
196
  @job_spec.delete('EX_ssh_key_paths')
144
197
  @job_spec.delete('sshfp')
@@ -154,68 +207,26 @@ module Aspera
154
207
  @builder.process_params
155
208
 
156
209
  # symbol must be index of Installation.paths
157
- if @builder.process_param('use_ascp4',:get_value)
210
+ if @builder.read_param('use_ascp4')
158
211
  env_args[:ascp_version] = :ascp4
159
212
  else
160
213
  env_args[:ascp_version] = :ascp
161
214
  # destination will be base64 encoded, put before path arguments
162
215
  @builder.add_command_line_options(['--dest64'])
163
216
  end
164
- # process file lists
165
- begin
166
- # is the file list provided through EX_ parameters?
167
- ascp_file_list_provided = self.class.ts_has_ascp_file_list(@job_spec)
168
- # set if paths is mandatory in ts
169
- @builder.params_definition['paths'][:mandatory] = !@job_spec.has_key?('keepalive') && !ascp_file_list_provided
170
- # get paths in transfer spec (after setting if it is mandatory)
171
- ts_paths_array = @builder.process_param('paths',:get_value)
172
- if ascp_file_list_provided && !ts_paths_array.nil?
173
- raise 'file list provided both in transfer spec and ascp file list. Remove one of them.'
174
- end
175
- # option 1: EX_file_list
176
- file_list_file = @builder.process_param('EX_file_list',:get_value)
177
- if !file_list_file.nil?
178
- option = '--file-list'
179
- else
180
- # option 2: EX_file_pair_list
181
- file_list_file = @builder.process_param('EX_file_pair_list',:get_value)
182
- if !file_list_file.nil?
183
- option = '--file-pair-list'
184
- elsif !ts_paths_array.nil?
185
- # option 3: in TS, it is an array
186
- if !self.class.file_list_folder.nil?
187
- # safer option: generate a file list file if there is storage defined for it
188
- # if there is destination in paths, then use filepairlist
189
- # TODO: well, we test only the first one, but anyway it shall be consistent
190
- if ts_paths_array.first.has_key?('destination')
191
- option = '--file-pair-list'
192
- lines = ts_paths_array.each_with_object([]){|e,m|m.push(e['source'],e['destination']);}
193
- else
194
- option = '--file-list'
195
- lines = ts_paths_array.map{|i|i['source']}
196
- end
197
- file_list_file = Aspera::TempFileManager.instance.new_file_path_in_folder(self.class.file_list_folder)
198
- File.write(file_list_file, lines.join("\n"))
199
- Log.log.debug{"#{option}=\n#{File.read(file_list_file)}".red}
200
- else
201
- # not safe for special characters ? (maybe not, depends on OS)
202
- Log.log.debug('placing source file list on command line (no file list file)')
203
- @builder.add_command_line_options(ts_paths_array.map{|i|i['source']})
204
- end
205
- end
206
- end
207
- @builder.add_command_line_options(["#{option}=#{file_list_file}"]) unless option.nil?
208
- end
217
+ # get list of files to transfer and build arg for ascp
218
+ process_file_list
209
219
  # optional args, at the end to override previous ones (to allow override)
210
- @builder.add_command_line_options(@builder.process_param('EX_ascp_args',:get_value))
220
+ @builder.add_command_line_options(@builder.read_param('EX_ascp_args'))
221
+ @builder.add_command_line_options(@opt_args)
211
222
  # process destination folder
212
- destination_folder = @builder.process_param('destination_root',:get_value) || '/'
223
+ destination_folder = @builder.read_param('destination_root') || '/'
213
224
  # ascp4 does not support base64 encoding of destination
214
225
  destination_folder = Base64.strict_encode64(destination_folder) unless env_args[:ascp_version].eql?(:ascp4)
215
226
  # destination MUST be last command line argument to ascp
216
227
  @builder.add_command_line_options([destination_folder])
217
228
 
218
- @builder.add_env_args(env_args[:env],env_args[:args])
229
+ @builder.add_env_args(env_args[:env], env_args[:args])
219
230
 
220
231
  return env_args
221
232
  end