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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.md +1267 -999
- data/bin/ascli +20 -1
- data/bin/asession +37 -34
- data/docs/test_env.conf +7 -3
- data/examples/aoc.rb +13 -12
- data/examples/dascli +23 -0
- data/examples/faspex4.rb +34 -29
- data/examples/{transfer.rb → node.rb} +31 -59
- data/examples/server.rb +93 -0
- data/lib/aspera/aoc.rb +153 -143
- data/lib/aspera/ascmd.rb +56 -45
- data/lib/aspera/ats_api.rb +9 -6
- data/lib/aspera/cli/basic_auth_plugin.rb +18 -16
- data/lib/aspera/cli/extended_value.rb +33 -30
- data/lib/aspera/cli/formater.rb +105 -111
- data/lib/aspera/cli/info.rb +3 -2
- data/lib/aspera/cli/listener/line_dump.rb +1 -0
- data/lib/aspera/cli/listener/logger.rb +1 -0
- data/lib/aspera/cli/listener/progress.rb +13 -12
- data/lib/aspera/cli/listener/progress_multi.rb +21 -20
- data/lib/aspera/cli/main.rb +110 -90
- data/lib/aspera/cli/manager.rb +99 -88
- data/lib/aspera/cli/plugin.rb +98 -39
- data/lib/aspera/cli/plugins/alee.rb +6 -5
- data/lib/aspera/cli/plugins/aoc.rb +581 -450
- data/lib/aspera/cli/plugins/ats.rb +84 -83
- data/lib/aspera/cli/plugins/bss.rb +30 -27
- data/lib/aspera/cli/plugins/config.rb +488 -397
- data/lib/aspera/cli/plugins/console.rb +17 -15
- data/lib/aspera/cli/plugins/cos.rb +26 -35
- data/lib/aspera/cli/plugins/faspex.rb +206 -172
- data/lib/aspera/cli/plugins/faspex5.rb +109 -74
- data/lib/aspera/cli/plugins/node.rb +379 -189
- data/lib/aspera/cli/plugins/orchestrator.rb +71 -65
- data/lib/aspera/cli/plugins/preview.rb +131 -122
- data/lib/aspera/cli/plugins/server.rb +50 -150
- data/lib/aspera/cli/plugins/shares.rb +61 -27
- data/lib/aspera/cli/plugins/sync.rb +15 -14
- data/lib/aspera/cli/transfer_agent.rb +75 -64
- data/lib/aspera/cli/version.rb +2 -1
- data/lib/aspera/colors.rb +29 -28
- data/lib/aspera/command_line_builder.rb +50 -43
- data/lib/aspera/cos_node.rb +64 -38
- data/lib/aspera/data_repository.rb +1 -0
- data/lib/aspera/environment.rb +33 -10
- data/lib/aspera/fasp/agent_base.rb +35 -30
- data/lib/aspera/fasp/agent_connect.rb +35 -30
- data/lib/aspera/fasp/agent_direct.rb +68 -60
- data/lib/aspera/fasp/agent_httpgw.rb +71 -64
- data/lib/aspera/fasp/agent_node.rb +24 -23
- data/lib/aspera/fasp/agent_trsdk.rb +19 -20
- data/lib/aspera/fasp/error.rb +2 -1
- data/lib/aspera/fasp/error_info.rb +79 -68
- data/lib/aspera/fasp/installation.rb +130 -126
- data/lib/aspera/fasp/listener.rb +1 -0
- data/lib/aspera/fasp/parameters.rb +71 -60
- data/lib/aspera/fasp/parameters.yaml +69 -17
- data/lib/aspera/fasp/resume_policy.rb +14 -11
- data/lib/aspera/fasp/transfer_spec.rb +6 -5
- data/lib/aspera/fasp/uri.rb +25 -24
- data/lib/aspera/faspex_gw.rb +83 -72
- data/lib/aspera/hash_ext.rb +23 -13
- data/lib/aspera/id_generator.rb +16 -13
- data/lib/aspera/keychain/encrypted_hash.rb +61 -46
- data/lib/aspera/keychain/macos_security.rb +26 -24
- data/lib/aspera/log.rb +35 -39
- data/lib/aspera/nagios.rb +36 -28
- data/lib/aspera/node.rb +19 -19
- data/lib/aspera/oauth.rb +120 -100
- data/lib/aspera/open_application.rb +25 -22
- data/lib/aspera/persistency_action_once.rb +9 -8
- data/lib/aspera/persistency_folder.rb +13 -9
- data/lib/aspera/preview/file_types.rb +261 -266
- data/lib/aspera/preview/generator.rb +74 -73
- data/lib/aspera/preview/image_error.png +0 -0
- data/lib/aspera/preview/options.rb +7 -6
- data/lib/aspera/preview/utils.rb +30 -33
- data/lib/aspera/preview/video_error.png +0 -0
- data/lib/aspera/proxy_auto_config.rb +27 -23
- data/lib/aspera/rest.rb +73 -74
- data/lib/aspera/rest_call_error.rb +1 -0
- data/lib/aspera/rest_error_analyzer.rb +23 -19
- data/lib/aspera/rest_errors_aspera.rb +43 -40
- data/lib/aspera/secret_hider.rb +74 -0
- data/lib/aspera/ssh.rb +13 -10
- data/lib/aspera/sync.rb +49 -47
- data/lib/aspera/temp_file_manager.rb +7 -5
- data/lib/aspera/timer_limiter.rb +9 -8
- data/lib/aspera/uri_reader.rb +17 -18
- data/lib/aspera/web_auth.rb +17 -15
- data.tar.gz.sig +5 -0
- metadata +119 -35
- metadata.gz.sig +0 -0
- 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,
|
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
|
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
|
66
|
-
options.add_opt_list(:file_access
|
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
|
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
|
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
|
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'
|
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
|
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
|
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'
|
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
|
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
|
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
|
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=[
|
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
|
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']
|
216
|
+
@default_transfer_spec['remote_host'] = @transfer_server_address
|
215
217
|
end
|
216
|
-
tspec
|
217
|
-
'direction'
|
218
|
-
'paths'
|
219
|
-
'tags'
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
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]
|
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
|
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
|
283
|
+
gen_infos = @preview_formats_to_generate.map do |preview_format|
|
282
284
|
{
|
283
|
-
preview_format:
|
284
|
-
base_dest:
|
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
|
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
|
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=[
|
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 [
|
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
|
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
|
417
|
+
node_info = @api_node.read('info')[:data]
|
416
418
|
Log.log.debug("root: #{node_info['docroot']}")
|
417
|
-
@access_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('/'
|
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.
|
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
|
431
|
+
@local_storage_root = @access_key_self['storage']['path']
|
429
432
|
#TODO: option to override @local_storage_root='xxx'
|
430
|
-
@local_storage_root
|
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.
|
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
|
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
|
451
|
-
scan_id=options.get_option(:scan_id
|
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
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
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
|
467
|
-
iteration_persistency=PersistencyActionOnce.new(
|
468
|
-
|
469
|
-
|
470
|
-
|
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
|
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
|