aspera-cli 4.7.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 (94) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +1 -0
  3. data/README.md +844 -861
  4. data/bin/ascli +20 -1
  5. data/bin/asession +37 -34
  6. data/docs/test_env.conf +11 -3
  7. data/examples/aoc.rb +13 -12
  8. data/examples/dascli +26 -0
  9. data/examples/faspex4.rb +34 -29
  10. data/examples/transfer.rb +30 -29
  11. data/lib/aspera/aoc.rb +151 -143
  12. data/lib/aspera/ascmd.rb +56 -45
  13. data/lib/aspera/ats_api.rb +6 -5
  14. data/lib/aspera/cli/basic_auth_plugin.rb +18 -16
  15. data/lib/aspera/cli/extended_value.rb +32 -30
  16. data/lib/aspera/cli/formater.rb +103 -111
  17. data/lib/aspera/cli/info.rb +2 -1
  18. data/lib/aspera/cli/listener/line_dump.rb +1 -0
  19. data/lib/aspera/cli/listener/logger.rb +1 -0
  20. data/lib/aspera/cli/listener/progress.rb +13 -12
  21. data/lib/aspera/cli/listener/progress_multi.rb +21 -20
  22. data/lib/aspera/cli/main.rb +106 -89
  23. data/lib/aspera/cli/manager.rb +96 -85
  24. data/lib/aspera/cli/plugin.rb +50 -32
  25. data/lib/aspera/cli/plugins/alee.rb +6 -5
  26. data/lib/aspera/cli/plugins/aoc.rb +521 -426
  27. data/lib/aspera/cli/plugins/ats.rb +84 -83
  28. data/lib/aspera/cli/plugins/bss.rb +30 -27
  29. data/lib/aspera/cli/plugins/config.rb +483 -397
  30. data/lib/aspera/cli/plugins/console.rb +17 -15
  31. data/lib/aspera/cli/plugins/cos.rb +26 -35
  32. data/lib/aspera/cli/plugins/faspex.rb +201 -168
  33. data/lib/aspera/cli/plugins/faspex5.rb +109 -74
  34. data/lib/aspera/cli/plugins/node.rb +378 -189
  35. data/lib/aspera/cli/plugins/orchestrator.rb +71 -65
  36. data/lib/aspera/cli/plugins/preview.rb +131 -122
  37. data/lib/aspera/cli/plugins/server.rb +94 -93
  38. data/lib/aspera/cli/plugins/shares.rb +42 -28
  39. data/lib/aspera/cli/plugins/sync.rb +15 -14
  40. data/lib/aspera/cli/transfer_agent.rb +56 -52
  41. data/lib/aspera/cli/version.rb +2 -1
  42. data/lib/aspera/colors.rb +29 -28
  43. data/lib/aspera/command_line_builder.rb +50 -43
  44. data/lib/aspera/cos_node.rb +64 -38
  45. data/lib/aspera/data_repository.rb +1 -0
  46. data/lib/aspera/environment.rb +18 -8
  47. data/lib/aspera/fasp/agent_base.rb +26 -23
  48. data/lib/aspera/fasp/agent_connect.rb +35 -30
  49. data/lib/aspera/fasp/agent_direct.rb +68 -60
  50. data/lib/aspera/fasp/agent_httpgw.rb +71 -64
  51. data/lib/aspera/fasp/agent_node.rb +24 -23
  52. data/lib/aspera/fasp/agent_trsdk.rb +19 -20
  53. data/lib/aspera/fasp/error.rb +2 -1
  54. data/lib/aspera/fasp/error_info.rb +79 -68
  55. data/lib/aspera/fasp/installation.rb +122 -114
  56. data/lib/aspera/fasp/listener.rb +1 -0
  57. data/lib/aspera/fasp/parameters.rb +44 -41
  58. data/lib/aspera/fasp/resume_policy.rb +14 -11
  59. data/lib/aspera/fasp/transfer_spec.rb +6 -5
  60. data/lib/aspera/fasp/uri.rb +25 -24
  61. data/lib/aspera/faspex_gw.rb +83 -72
  62. data/lib/aspera/hash_ext.rb +10 -12
  63. data/lib/aspera/id_generator.rb +8 -7
  64. data/lib/aspera/keychain/encrypted_hash.rb +60 -45
  65. data/lib/aspera/keychain/macos_security.rb +26 -24
  66. data/lib/aspera/log.rb +34 -38
  67. data/lib/aspera/nagios.rb +14 -13
  68. data/lib/aspera/node.rb +19 -19
  69. data/lib/aspera/oauth.rb +121 -101
  70. data/lib/aspera/open_application.rb +6 -5
  71. data/lib/aspera/persistency_action_once.rb +9 -8
  72. data/lib/aspera/persistency_folder.rb +10 -9
  73. data/lib/aspera/preview/file_types.rb +261 -266
  74. data/lib/aspera/preview/generator.rb +74 -73
  75. data/lib/aspera/preview/image_error.png +0 -0
  76. data/lib/aspera/preview/options.rb +7 -6
  77. data/lib/aspera/preview/utils.rb +30 -33
  78. data/lib/aspera/preview/video_error.png +0 -0
  79. data/lib/aspera/proxy_auto_config.rb +25 -23
  80. data/lib/aspera/rest.rb +73 -74
  81. data/lib/aspera/rest_call_error.rb +1 -0
  82. data/lib/aspera/rest_error_analyzer.rb +11 -9
  83. data/lib/aspera/rest_errors_aspera.rb +5 -4
  84. data/lib/aspera/secret_hider.rb +68 -0
  85. data/lib/aspera/ssh.rb +12 -10
  86. data/lib/aspera/sync.rb +49 -47
  87. data/lib/aspera/temp_file_manager.rb +7 -5
  88. data/lib/aspera/timer_limiter.rb +9 -8
  89. data/lib/aspera/uri_reader.rb +11 -14
  90. data/lib/aspera/web_auth.rb +17 -15
  91. data.tar.gz.sig +0 -0
  92. metadata +117 -34
  93. metadata.gz.sig +2 -0
  94. data/bin/dascli +0 -13
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'aspera/cli/basic_auth_plugin'
3
4
  require 'aspera/preview/generator'
4
5
  require 'aspera/preview/options'
@@ -18,32 +19,33 @@ module Aspera
18
19
  module Plugins
19
20
  class Preview < BasicAuthPlugin
20
21
  # special tag to identify transfers related to generator
21
- PREV_GEN_TAG='preview_generator'
22
+ PREV_GEN_TAG = 'preview_generator'
22
23
  # defined by node API: suffix for folder containing previews
23
- PREVIEW_FOLDER_SUFFIX='.asp-preview'
24
+ PREVIEW_FOLDER_SUFFIX = '.asp-preview'
24
25
  # basename of preview files
25
- PREVIEW_BASENAME='preview'
26
+ PREVIEW_BASENAME = 'preview'
26
27
  # subfolder in system tmp folder
27
- TMP_DIR_PREFIX='prev_tmp'
28
- DEFAULT_PREVIEWS_FOLDER='previews'
29
- AK_MARKER_FILE='.aspera_access_key'
30
- LOCAL_STORAGE_PCVL='file:///'
31
- LOG_LIMITER_SEC=30.0
32
- private_constant :PREV_GEN_TAG, :PREVIEW_FOLDER_SUFFIX, :PREVIEW_BASENAME, :TMP_DIR_PREFIX, :DEFAULT_PREVIEWS_FOLDER, :LOCAL_STORAGE_PCVL, :AK_MARKER_FILE, :LOG_LIMITER_SEC
28
+ TMP_DIR_PREFIX = 'prev_tmp'
29
+ DEFAULT_PREVIEWS_FOLDER = 'previews'
30
+ AK_MARKER_FILE = '.aspera_access_key'
31
+ LOCAL_STORAGE_PCVL = 'file:///'
32
+ LOG_LIMITER_SEC = 30.0
33
+ private_constant :PREV_GEN_TAG, :PREVIEW_FOLDER_SUFFIX, :PREVIEW_BASENAME, :TMP_DIR_PREFIX, :DEFAULT_PREVIEWS_FOLDER,
34
+ :LOCAL_STORAGE_PCVL, :AK_MARKER_FILE, :LOG_LIMITER_SEC
33
35
 
34
36
  # option_skip_format has special accessors
35
37
  attr_accessor :option_previews_folder
36
38
  attr_accessor :option_folder_reset_cache, :option_skip_folders, :option_overwrite, :option_file_access
37
39
  def initialize(env)
38
40
  super(env)
39
- @skip_types=[]
40
- @default_transfer_spec=nil
41
+ @skip_types = []
42
+ @default_transfer_spec = nil
41
43
  # by default generate all supported formats (clone, as altered by options)
42
- @preview_formats_to_generate=Aspera::Preview::Generator::PREVIEW_FORMATS.clone
44
+ @preview_formats_to_generate = Aspera::Preview::Generator::PREVIEW_FORMATS.clone
43
45
  # options for generation
44
- @gen_options=Aspera::Preview::Options.new
46
+ @gen_options = Aspera::Preview::Options.new
45
47
  # used to trigger periodic processing
46
- @periodic=TimerLimiter.new(LOG_LIMITER_SEC)
48
+ @periodic = TimerLimiter.new(LOG_LIMITER_SEC)
47
49
  # link CLI options to gen_info attributes
48
50
  options.set_obj_attr(:skip_format,self,:option_skip_format,[]) # no skip
49
51
  options.set_obj_attr(:folder_reset_cache,self,:option_folder_reset_cache,:no)
@@ -53,7 +55,7 @@ module Aspera
53
55
  options.set_obj_attr(:overwrite,self,:option_overwrite,:mtime)
54
56
  options.set_obj_attr(:file_access,self,:option_file_access,:local)
55
57
  options.add_opt_list(:skip_format,Aspera::Preview::Generator::PREVIEW_FORMATS,'skip this preview format (multiple possible)')
56
- options.add_opt_list(:folder_reset_cache,[:no,:header,:read],'force detection of generated preview by refresh cache')
58
+ options.add_opt_list(:folder_reset_cache,%i[no header read],'force detection of generated preview by refresh cache')
57
59
  options.add_opt_simple(:skip_types,'skip types in comma separated list')
58
60
  options.add_opt_simple(:previews_folder,'preview folder in storage root')
59
61
  options.add_opt_simple(:temp_folder,'path to temp folder')
@@ -62,8 +64,8 @@ module Aspera
62
64
  options.add_opt_simple(:scan_path,'subpath in folder id to start scan in (default=/)')
63
65
  options.add_opt_simple(:scan_id,'forder id in storage to start scan in, default is access key main folder id')
64
66
  options.add_opt_boolean(:mimemagic,'use Mime type detection of gem mimemagic')
65
- options.add_opt_list(:overwrite,[:always,:never,:mtime],'when to overwrite result file')
66
- options.add_opt_list(:file_access,[:local,:remote],'how to read and write files in repository')
67
+ options.add_opt_list(:overwrite,%i[always never mtime],'when to overwrite result file')
68
+ options.add_opt_list(:file_access,%i[local remote],'how to read and write files in repository')
67
69
  options.set_option(:temp_folder,Dir.tmpdir)
68
70
  options.set_option(:mimemagic,false)
69
71
 
@@ -72,7 +74,7 @@ module Aspera
72
74
  options.set_obj_attr(opt[:name],@gen_options,opt[:name],opt[:default])
73
75
  if opt.has_key?(:values)
74
76
  options.add_opt_list(opt[:name],opt[:values],opt[:description])
75
- elsif [:yes,:no].include?(opt[:default])
77
+ elsif Cli::Manager::BOOLEAN_SIMPLE.include?(opt[:default])
76
78
  options.add_opt_boolean(opt[:name],opt[:description])
77
79
  else
78
80
  options.add_opt_simple(opt[:name],opt[:description])
@@ -81,15 +83,15 @@ module Aspera
81
83
 
82
84
  options.parse_options!
83
85
  raise 'skip_folder shall be an Array, use @json:[...]' unless @option_skip_folders.is_a?(Array)
84
- @tmp_folder=File.join(options.get_option(:temp_folder,:mandatory),"#{TMP_DIR_PREFIX}.#{SecureRandom.uuid}")
86
+ @tmp_folder = File.join(options.get_option(:temp_folder,is_type: :mandatory),"#{TMP_DIR_PREFIX}.#{SecureRandom.uuid}")
85
87
  FileUtils.mkdir_p(@tmp_folder)
86
88
  Log.log.debug("tmpdir: #{@tmp_folder}")
87
89
  end
88
90
 
89
91
  def option_skip_types=(value)
90
- @skip_types=[]
92
+ @skip_types = []
91
93
  value.split(',').each do |v|
92
- s=v.to_sym
94
+ s = v.to_sym
93
95
  raise "not supported: #{v}" unless Aspera::Preview::FileTypes::CONVERSION_TYPES.include?(s)
94
96
  @skip_types.push(s)
95
97
  end
@@ -110,8 +112,8 @@ module Aspera
110
112
  # /files/id/files is normally cached in redis, but we can discard the cache
111
113
  # but /files/id is not cached
112
114
  def get_folder_entries(file_id,request_args=nil)
113
- headers={'Accept'=>'application/json'}
114
- headers.merge!({'X-Aspera-Cache-Control'=>'no-cache'}) if @option_folder_reset_cache.eql?(:header)
115
+ headers = {'Accept' => 'application/json'}
116
+ headers['X-Aspera-Cache-Control'] = 'no-cache' if @option_folder_reset_cache.eql?(:header)
115
117
  return @api_node.call({operation: 'GET',subpath: "files/#{file_id}/files",headers: headers,url_params: request_args})[:data]
116
118
  #return @api_node.read("files/#{file_id}/files",request_args)[:data]
117
119
  end
@@ -119,14 +121,14 @@ module Aspera
119
121
  # old version based on folders
120
122
  # @param iteration_persistency can be nil
121
123
  def process_trevents(iteration_persistency)
122
- events_filter={
123
- 'access_key'=>@access_key_self['id'],
124
- 'type'=>'download.ended'
124
+ events_filter = {
125
+ 'access_key' => @access_key_self['id'],
126
+ 'type' => 'download.ended'
125
127
  }
126
128
  # optionally add iteration token from persistency
127
- events_filter['iteration_token']=iteration_persistency.data.first unless iteration_persistency.nil?
129
+ events_filter['iteration_token'] = iteration_persistency.data.first unless iteration_persistency.nil?
128
130
  begin
129
- events=@api_node.read('events',events_filter)[:data]
131
+ events = @api_node.read('events',events_filter)[:data]
130
132
  rescue RestCallError => e
131
133
  if e.message.include?('Invalid iteration_token')
132
134
  Log.log.warn("Retrying without iteration token: #{e}")
@@ -141,10 +143,10 @@ module Aspera
141
143
  event['data']['status'].eql?('completed') &&
142
144
  event['data']['error_code'].eql?(0) &&
143
145
  event['data'].dig('tags','aspera',PREV_GEN_TAG).nil?
144
- folder_id=event.dig('data','tags','aspera','node','file_id')
145
- folder_id||=event.dig('data','file_id')
146
+ folder_id = event.dig('data','tags','aspera','node','file_id')
147
+ folder_id ||= event.dig('data','file_id')
146
148
  if !folder_id.nil?
147
- folder_entry=@api_node.read("files/#{folder_id}")[:data] rescue nil
149
+ folder_entry = @api_node.read("files/#{folder_id}")[:data] rescue nil
148
150
  scan_folder_files(folder_entry) unless folder_entry.nil?
149
151
  end
150
152
  end
@@ -153,7 +155,7 @@ module Aspera
153
155
  Log.log.info("Processed event #{event['id']}")
154
156
  # save checkpoint to avoid losing processing in case of error
155
157
  if !iteration_persistency.nil?
156
- iteration_persistency.data[0]=event['id'].to_s
158
+ iteration_persistency.data[0] = event['id'].to_s
157
159
  iteration_persistency.save
158
160
  end
159
161
  end
@@ -162,21 +164,21 @@ module Aspera
162
164
  # requests recent events on node api and process newly modified folders
163
165
  def process_events(iteration_persistency)
164
166
  # get new file creation by access key (TODO: what if file already existed?)
165
- events_filter={
166
- 'access_key'=>@access_key_self['id'],
167
- 'type'=>'file.*'
167
+ events_filter = {
168
+ 'access_key' => @access_key_self['id'],
169
+ 'type' => 'file.*'
168
170
  }
169
171
  # optionally add iteration token from persistency
170
- events_filter['iteration_token']=iteration_persistency.data.first unless iteration_persistency.nil?
171
- events=@api_node.read('events',events_filter)[:data]
172
+ events_filter['iteration_token'] = iteration_persistency.data.first unless iteration_persistency.nil?
173
+ events = @api_node.read('events',events_filter)[:data]
172
174
  return if events.empty?
173
175
  events.each do |event|
174
176
  # process only files
175
177
  if event.dig('data','type').eql?('file')
176
- file_entry=@api_node.read("files/#{event['data']['id']}")[:data] rescue nil
178
+ file_entry = @api_node.read("files/#{event['data']['id']}")[:data] rescue nil
177
179
  if !file_entry.nil? &&
178
180
  @option_skip_folders.select{|d|file_entry['path'].start_with?(d)}.empty?
179
- file_entry['parent_file_id']=event['data']['parent_file_id']
181
+ file_entry['parent_file_id'] = event['data']['parent_file_id']
180
182
  if event['types'].include?('file.deleted')
181
183
  Log.log.error('TODO'.red)
182
184
  end
@@ -190,7 +192,7 @@ module Aspera
190
192
  Log.log.info("Processing event #{event['id']}")
191
193
  # save checkpoint to avoid losing processing in case of error
192
194
  if !iteration_persistency.nil?
193
- iteration_persistency.data[0]=event['id'].to_s
195
+ iteration_persistency.data[0] = event['id'].to_s
194
196
  iteration_persistency.save
195
197
  end
196
198
  end
@@ -200,44 +202,44 @@ module Aspera
200
202
  raise 'error' if destination.nil? && direction.eql?(Fasp::TransferSpec::DIRECTION_RECEIVE)
201
203
  if @default_transfer_spec.nil?
202
204
  # make a dummy call to get some default transfer parameters
203
- res=@api_node.create('files/upload_setup',{'transfer_requests'=>[{'transfer_request'=>{'paths'=>[{}],'destination_root'=>'/'}}]})
204
- template_ts=res[:data]['transfer_specs'].first['transfer_spec']
205
+ res = @api_node.create('files/upload_setup',{'transfer_requests' => [{'transfer_request' => {'paths' => [{}],'destination_root' => '/'}}]})
206
+ template_ts = res[:data]['transfer_specs'].first['transfer_spec']
205
207
  # get ports, anyway that should be 33001 for both. add remote_user ?
206
- @default_transfer_spec=['ssh_port','fasp_port'].each_with_object({}){|e,h|h[e]=template_ts[e];}
208
+ @default_transfer_spec = %w[ssh_port fasp_port].each_with_object({}){|e,h|h[e] = template_ts[e];}
207
209
  if !@default_transfer_spec['remote_user'].eql?(Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER)
208
210
  Log.log.warn('remote_user shall be xfer')
209
- @default_transfer_spec['remote_user']=Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER
211
+ @default_transfer_spec['remote_user'] = Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER
210
212
  end
211
- Aspera::Node.set_ak_basic_token(@default_transfer_spec,@access_key_self['id'],options.get_option(:password,:mandatory))
213
+ Aspera::Node.set_ak_basic_token(@default_transfer_spec,@access_key_self['id'],options.get_option(:password,is_type: :mandatory))
212
214
  # note: we use the same address for ascp than for node api instead of the one from upload_setup
213
215
  # TODO: configurable ? useful ?
214
- @default_transfer_spec['remote_host']=@transfer_server_address
216
+ @default_transfer_spec['remote_host'] = @transfer_server_address
215
217
  end
216
- tspec=@default_transfer_spec.merge({
217
- 'direction' => direction,
218
- 'paths' => [{'source'=>source_filename}],
219
- 'tags' => { 'aspera' => {
220
- PREV_GEN_TAG => true,
221
- 'node' => {
222
- 'access_key' => @access_key_self['id'],
223
- 'file_id' => folder_id }}}
218
+ tspec = @default_transfer_spec.merge({
219
+ 'direction' => direction,
220
+ 'paths' => [{'source' => source_filename}],
221
+ 'tags' => { 'aspera' => {
222
+ PREV_GEN_TAG => true,
223
+ 'node' => {
224
+ 'access_key' => @access_key_self['id'],
225
+ 'file_id' => folder_id }}}
224
226
  })
225
227
  # force destination
226
228
  # tspec['destination_root']=destination
227
- transfer.option_transfer_spec_deep_merge({'destination_root'=>destination})
229
+ transfer.option_transfer_spec_deep_merge({'destination_root' => destination})
228
230
  Main.result_transfer(transfer.start(tspec,{src: :node_gen4}))
229
231
  end
230
232
 
231
233
  def get_infos_local(gen_infos,entry)
232
- local_original_filepath=File.join(@local_storage_root,entry['path'])
233
- original_mtime=File.mtime(local_original_filepath)
234
+ local_original_filepath = File.join(@local_storage_root,entry['path'])
235
+ original_mtime = File.mtime(local_original_filepath)
234
236
  # out
235
- local_entry_preview_dir=File.join(@local_preview_folder, entry_preview_folder_name(entry))
237
+ local_entry_preview_dir = File.join(@local_preview_folder, entry_preview_folder_name(entry))
236
238
  gen_infos.each do |gen_info|
237
- gen_info[:src]=local_original_filepath
238
- gen_info[:dst]=File.join(local_entry_preview_dir, gen_info[:base_dest])
239
- gen_info[:preview_exist]=File.exist?(gen_info[:dst])
240
- gen_info[:preview_newer_than_original] = (gen_info[:preview_exist] and (File.mtime(gen_info[:dst])>original_mtime))
239
+ gen_info[:src] = local_original_filepath
240
+ gen_info[:dst] = File.join(local_entry_preview_dir, gen_info[:base_dest])
241
+ gen_info[:preview_exist] = File.exist?(gen_info[:dst])
242
+ gen_info[:preview_newer_than_original] = (gen_info[:preview_exist] && (File.mtime(gen_info[:dst]) > original_mtime))
241
243
  end
242
244
  return local_entry_preview_dir
243
245
  end
@@ -245,19 +247,19 @@ module Aspera
245
247
  def get_infos_remote(gen_infos,entry)
246
248
  #Log.log.debug(">>>> get_infos_remote #{entry}".red)
247
249
  # store source directly here
248
- local_original_filepath=File.join(@tmp_folder,entry['name'])
250
+ local_original_filepath = File.join(@tmp_folder,entry['name'])
249
251
  #original_mtime=DateTime.parse(entry['modified_time'])
250
252
  # out: where previews are generated
251
- local_entry_preview_dir=File.join(@tmp_folder,entry_preview_folder_name(entry))
252
- file_info=@api_node.read("files/#{entry['id']}")[:data]
253
+ local_entry_preview_dir = File.join(@tmp_folder,entry_preview_folder_name(entry))
254
+ file_info = @api_node.read("files/#{entry['id']}")[:data]
253
255
  #TODO: this does not work because previews is hidden in api (gen4)
254
256
  #this_preview_folder_entries=get_folder_entries(@previews_folder_entry['id'],{name: @entry_preview_folder_name})
255
257
  # TODO: use gen3 api to list files and get date
256
258
  gen_infos.each do |gen_info|
257
- gen_info[:src]=local_original_filepath
258
- gen_info[:dst]=File.join(local_entry_preview_dir, gen_info[:base_dest])
259
+ gen_info[:src] = local_original_filepath
260
+ gen_info[:dst] = File.join(local_entry_preview_dir, gen_info[:base_dest])
259
261
  # TODO: use this_preview_folder_entries (but it's hidden)
260
- gen_info[:preview_exist]=file_info.has_key?('preview')
262
+ gen_info[:preview_exist] = file_info.has_key?('preview')
261
263
  # TODO: get change time and compare, useful ?
262
264
  gen_info[:preview_newer_than_original] = gen_info[:preview_exist]
263
265
  end
@@ -270,7 +272,7 @@ module Aspera
270
272
  end
271
273
 
272
274
  def preview_filename(preview_format,filename=nil)
273
- filename||=PREVIEW_BASENAME
275
+ filename ||= PREVIEW_BASENAME
274
276
  return "#{filename}.#{preview_format}"
275
277
  end
276
278
 
@@ -278,16 +280,16 @@ module Aspera
278
280
  # entry must contain "parent_file_id" if remote.
279
281
  def generate_preview(entry)
280
282
  # prepare generic information
281
- gen_infos=@preview_formats_to_generate.map do |preview_format|
283
+ gen_infos = @preview_formats_to_generate.map do |preview_format|
282
284
  {
283
- preview_format: preview_format,
284
- base_dest: preview_filename(preview_format)
285
+ preview_format: preview_format,
286
+ base_dest: preview_filename(preview_format)
285
287
  }
286
288
  end
287
289
  # lets gather some infos on possibly existing previews
288
290
  # it depends if files access locally or remotely
289
291
  # folder where previews will be generated for this particular entry
290
- local_entry_preview_dir=@access_remote ? get_infos_remote(gen_infos,entry) : get_infos_local(gen_infos,entry)
292
+ local_entry_preview_dir = @access_remote ? get_infos_remote(gen_infos,entry) : get_infos_local(gen_infos,entry)
291
293
  # here we have the status on preview files
292
294
  # let's find if they need generation
293
295
  gen_infos.select! do |gen_info|
@@ -305,7 +307,7 @@ module Aspera
305
307
  end
306
308
  end
307
309
  # need generator for further checks
308
- gen_info[:generator]=Aspera::Preview::Generator.new(@gen_options,gen_info[:src],gen_info[:dst],@tmp_folder,entry['content_type'])
310
+ gen_info[:generator] = Aspera::Preview::Generator.new(@gen_options,gen_info[:src],gen_info[:dst],@tmp_folder,entry['content_type'])
309
311
  # get conversion_type (if known) and check if supported
310
312
  next false unless gen_info[:generator].supported?
311
313
  # shall we skip it ?
@@ -346,19 +348,19 @@ module Aspera
346
348
  def scan_folder_files(top_entry,scan_start=nil)
347
349
  if !scan_start.nil?
348
350
  # canonical path: start with / and ends with /
349
- scan_start='/'+scan_start.split('/').reject(&:empty?).join('/')
350
- scan_start="#{scan_start}/" #unless scan_start.end_with?('/')
351
+ scan_start = '/' + scan_start.split('/').reject(&:empty?).join('/')
352
+ scan_start = "#{scan_start}/" #unless scan_start.end_with?('/')
351
353
  end
352
- filter_block=Aspera::Node.file_matcher(options.get_option(:value,:optional))
354
+ filter_block = Aspera::Node.file_matcher(options.get_option(:value))
353
355
  Log.log.debug("scan: #{top_entry} : #{scan_start}".green)
354
356
  # don't use recursive call, use list instead
355
- entries_to_process=[top_entry]
357
+ entries_to_process = [top_entry]
356
358
  while !entries_to_process.empty?
357
- entry=entries_to_process.shift
359
+ entry = entries_to_process.shift
358
360
  # process this entry only if it is within the scan_start
359
- entry_path_with_slash=entry['path']
361
+ entry_path_with_slash = entry['path']
360
362
  Log.log.info("processing entry #{entry_path_with_slash}") if @periodic.trigger?
361
- entry_path_with_slash="#{entry_path_with_slash}/" unless entry_path_with_slash.end_with?('/')
363
+ entry_path_with_slash = "#{entry_path_with_slash}/" unless entry_path_with_slash.end_with?('/')
362
364
  if !scan_start.nil? && !scan_start.start_with?(entry_path_with_slash) && !entry_path_with_slash.start_with?(scan_start)
363
365
  Log.log.debug("#{entry['path']} folder (skip start)".bg_red)
364
366
  next
@@ -380,14 +382,14 @@ module Aspera
380
382
  else
381
383
  Log.log.debug("#{entry['path']} folder".green)
382
384
  # get folder content
383
- folder_entries=get_folder_entries(entry['id'])
385
+ folder_entries = get_folder_entries(entry['id'])
384
386
  # process all items in current folder
385
387
  folder_entries.each do |folder_entry|
386
388
  # add path for older versions of ES
387
389
  if !folder_entry.has_key?('path')
388
- folder_entry['path']=entry_path_with_slash+folder_entry['name']
390
+ folder_entry['path'] = entry_path_with_slash + folder_entry['name']
389
391
  end
390
- folder_entry['parent_file_id']=entry['id']
392
+ folder_entry['parent_file_id'] = entry['id']
391
393
  entries_to_process.push(folder_entry)
392
394
  end
393
395
  end
@@ -400,74 +402,81 @@ module Aspera
400
402
  end
401
403
  end
402
404
 
403
- ACTIONS=[:scan,:events,:trevents,:check,:test]
405
+ ACTIONS = %i[scan events trevents check test].freeze
404
406
 
405
407
  def execute_action
406
- command=options.get_next_command(ACTIONS)
407
- unless [:check,:test].include?(command)
408
+ command = options.get_next_command(ACTIONS)
409
+ unless %i[check test].include?(command)
408
410
  # this will use node api
409
- @api_node=basic_auth_api
410
- @transfer_server_address=URI.parse(@api_node.params[:base_url]).host
411
+ @api_node = basic_auth_api
412
+ @transfer_server_address = URI.parse(@api_node.params[:base_url]).host
411
413
  # get current access key
412
- @access_key_self=@api_node.read('access_keys/self')[:data]
414
+ @access_key_self = @api_node.read('access_keys/self')[:data]
413
415
  # TODO: check events is activated here:
414
416
  # note that docroot is good to look at as well
415
- node_info=@api_node.read('info')[:data]
417
+ node_info = @api_node.read('info')[:data]
416
418
  Log.log.debug("root: #{node_info['docroot']}")
417
- @access_remote=@option_file_access.eql?(:remote)
419
+ @access_remote = @option_file_access.eql?(:remote)
418
420
  Log.log.debug("remote: #{@access_remote}")
419
421
  Log.log.debug("access key info: #{@access_key_self}")
420
422
  #TODO: can the previews folder parameter be read from node api ?
421
- @option_skip_folders.push('/'+@option_previews_folder)
423
+ @option_skip_folders.push('/' + @option_previews_folder)
422
424
  if @access_remote
423
425
  # note the filter "name", it's why we take the first one
424
- @previews_folder_entry=get_folder_entries(@access_key_self['root_file_id'],{name: @option_previews_folder}).first
425
- raise CliError,"Folder #{@option_previews_folder} does not exist on node. Please create it in the storage root, or specify an alternate name." if @previews_folder_entry.nil?
426
+ @previews_folder_entry = get_folder_entries(@access_key_self['root_file_id'],{name: @option_previews_folder}).first
427
+ raise CliError,"Folder #{@option_previews_folder} does not exist on node. "\
428
+ 'Please create it in the storage root, or specify an alternate name.' if @previews_folder_entry.nil?
426
429
  else
427
430
  raise 'only local storage allowed in this mode' unless @access_key_self['storage']['type'].eql?('local')
428
- @local_storage_root=@access_key_self['storage']['path']
431
+ @local_storage_root = @access_key_self['storage']['path']
429
432
  #TODO: option to override @local_storage_root='xxx'
430
- @local_storage_root=@local_storage_root[LOCAL_STORAGE_PCVL.length..-1] if @local_storage_root.start_with?(LOCAL_STORAGE_PCVL)
433
+ @local_storage_root = @local_storage_root[LOCAL_STORAGE_PCVL.length..-1] if @local_storage_root.start_with?(LOCAL_STORAGE_PCVL)
431
434
  #TODO: windows could have "C:" ?
432
435
  raise "not local storage: #{@local_storage_root}" unless @local_storage_root.start_with?('/')
433
436
  raise CliError,"Local storage root folder #{@local_storage_root} does not exist." unless File.directory?(@local_storage_root)
434
- @local_preview_folder=File.join(@local_storage_root,@option_previews_folder)
435
- raise CliError,"Folder #{@local_preview_folder} does not exist locally. Please create it, or specify an alternate name." unless File.directory?(@local_preview_folder)
437
+ @local_preview_folder = File.join(@local_storage_root,@option_previews_folder)
438
+ raise CliError,"Folder #{@local_preview_folder} does not exist locally. "\
439
+ 'Please create it, or specify an alternate name.' unless File.directory?(@local_preview_folder)
436
440
  # protection to avoid clash of file id for two different access keys
437
- marker_file=File.join(@local_preview_folder,AK_MARKER_FILE)
441
+ marker_file = File.join(@local_preview_folder,AK_MARKER_FILE)
438
442
  Log.log.debug("marker file: #{marker_file}")
439
443
  if File.exist?(marker_file)
440
- ak=File.read(marker_file)
444
+ ak = File.read(marker_file).chomp
441
445
  raise "mismatch access key in #{marker_file}: contains #{ak}, using #{@access_key_self['id']}" unless @access_key_self['id'].eql?(ak)
442
446
  else
443
447
  File.write(marker_file,@access_key_self['id'])
444
448
  end
445
449
  end
446
450
  end
447
- Aspera::Preview::FileTypes.instance.use_mimemagic = options.get_option(:mimemagic,:mandatory)
451
+ Aspera::Preview::FileTypes.instance.use_mimemagic = options.get_option(:mimemagic,is_type: :mandatory)
448
452
  case command
449
453
  when :scan
450
- scan_path=options.get_option(:scan_path,:optional)
451
- scan_id=options.get_option(:scan_id,:optional)
454
+ scan_path = options.get_option(:scan_path)
455
+ scan_id = options.get_option(:scan_id)
452
456
  # by default start at root
453
- folder_info=
454
- if scan_id.nil?
455
- { 'id' => @access_key_self['root_file_id'],
456
- 'name' => '/',
457
- 'type' => 'folder',
458
- 'path' => '/' }
459
- else
460
- @api_node.read("files/#{scan_id}")[:data]
461
- end
457
+ folder_info =
458
+ if scan_id.nil?
459
+ { 'id' => @access_key_self['root_file_id'],
460
+ 'name' => '/',
461
+ 'type' => 'folder',
462
+ 'path' => '/' }
463
+ else
464
+ @api_node.read("files/#{scan_id}")[:data]
465
+ end
462
466
  scan_folder_files(folder_info,scan_path)
463
467
  return Main.result_status('scan finished')
464
468
  when :events,:trevents
465
- iteration_persistency=nil
466
- if options.get_option(:once_only,:mandatory)
467
- iteration_persistency=PersistencyActionOnce.new(
468
- manager: @agents[:persistency],
469
- data: [],
470
- id: IdGenerator.from_list(['preview_iteration',command.to_s,options.get_option(:url,:mandatory),options.get_option(:username,:mandatory)]))
469
+ iteration_persistency = nil
470
+ if options.get_option(:once_only,is_type: :mandatory)
471
+ iteration_persistency = PersistencyActionOnce.new(
472
+ manager: @agents[:persistency],
473
+ data: [],
474
+ id: IdGenerator.from_list([
475
+ 'preview_iteration',
476
+ command.to_s,
477
+ options.get_option(:url,is_type: :mandatory),
478
+ options.get_option(:username,is_type: :mandatory)
479
+ ]))
471
480
  end
472
481
  # call processing method specified by command line command
473
482
  send("process_#{command}",iteration_persistency)
@@ -476,10 +485,10 @@ module Aspera
476
485
  Aspera::Preview::Utils.check_tools(@skip_types)
477
486
  return Main.result_status('tools validated')
478
487
  when :test
479
- format = options.get_next_argument('format',Aspera::Preview::Generator::PREVIEW_FORMATS)
488
+ format = options.get_next_argument('format',expected: Aspera::Preview::Generator::PREVIEW_FORMATS)
480
489
  source = options.get_next_argument('source file')
481
- dest=preview_filename(format,options.get_option(:case,:optional))
482
- g=Aspera::Preview::Generator.new(@gen_options,source,dest,@tmp_folder,nil)
490
+ dest = preview_filename(format,options.get_option(:case))
491
+ g = Aspera::Preview::Generator.new(@gen_options,source,dest,@tmp_folder,nil)
483
492
  raise "cannot find file type for #{source}" if g.conversion_type.nil?
484
493
  raise "out format #{format} not supported" unless g.supported?
485
494
  g.generate