aspera-cli 4.13.0 → 4.15.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/CHANGELOG.md +81 -7
- data/CONTRIBUTING.md +22 -6
- data/README.md +2038 -1080
- data/bin/ascli +18 -9
- data/bin/asession +12 -14
- data/examples/dascli +1 -1
- data/examples/proxy.pac +1 -1
- data/examples/rubyc +24 -0
- data/lib/aspera/aoc.rb +219 -159
- data/lib/aspera/ascmd.rb +25 -14
- data/lib/aspera/cli/basic_auth_plugin.rb +12 -9
- data/lib/aspera/cli/error.rb +17 -0
- data/lib/aspera/cli/extended_value.rb +47 -12
- data/lib/aspera/cli/formatter.rb +260 -179
- data/lib/aspera/cli/hints.rb +80 -0
- data/lib/aspera/cli/main.rb +104 -156
- data/lib/aspera/cli/manager.rb +259 -209
- data/lib/aspera/cli/plugin.rb +123 -63
- data/lib/aspera/cli/plugins/alee.rb +2 -3
- data/lib/aspera/cli/plugins/aoc.rb +341 -261
- data/lib/aspera/cli/plugins/ats.rb +22 -21
- data/lib/aspera/cli/plugins/bss.rb +5 -5
- data/lib/aspera/cli/plugins/config.rb +578 -627
- data/lib/aspera/cli/plugins/console.rb +44 -6
- data/lib/aspera/cli/plugins/cos.rb +15 -17
- data/lib/aspera/cli/plugins/faspex.rb +114 -100
- data/lib/aspera/cli/plugins/faspex5.rb +411 -264
- data/lib/aspera/cli/plugins/node.rb +354 -259
- data/lib/aspera/cli/plugins/orchestrator.rb +61 -29
- data/lib/aspera/cli/plugins/preview.rb +82 -90
- data/lib/aspera/cli/plugins/server.rb +79 -32
- data/lib/aspera/cli/plugins/shares.rb +55 -42
- data/lib/aspera/cli/sync_actions.rb +68 -0
- data/lib/aspera/cli/transfer_agent.rb +66 -73
- data/lib/aspera/cli/transfer_progress.rb +74 -0
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +12 -8
- data/lib/aspera/command_line_builder.rb +14 -11
- data/lib/aspera/cos_node.rb +3 -2
- data/lib/aspera/data/6 +0 -0
- data/lib/aspera/environment.rb +24 -9
- data/lib/aspera/fasp/agent_aspera.rb +126 -0
- data/lib/aspera/fasp/agent_base.rb +31 -77
- data/lib/aspera/fasp/agent_connect.rb +25 -21
- data/lib/aspera/fasp/agent_direct.rb +89 -103
- data/lib/aspera/fasp/agent_httpgw.rb +231 -149
- data/lib/aspera/fasp/agent_node.rb +41 -34
- data/lib/aspera/fasp/agent_trsdk.rb +75 -32
- data/lib/aspera/fasp/error_info.rb +4 -2
- data/lib/aspera/fasp/faux_file.rb +52 -0
- data/lib/aspera/fasp/installation.rb +53 -195
- data/lib/aspera/fasp/management.rb +244 -0
- data/lib/aspera/fasp/parameters.rb +71 -37
- data/lib/aspera/fasp/parameters.yaml +76 -8
- data/lib/aspera/fasp/products.rb +162 -0
- data/lib/aspera/fasp/resume_policy.rb +3 -3
- data/lib/aspera/fasp/transfer_spec.rb +7 -6
- data/lib/aspera/fasp/uri.rb +26 -24
- data/lib/aspera/faspex_gw.rb +2 -2
- data/lib/aspera/faspex_postproc.rb +2 -2
- data/lib/aspera/hash_ext.rb +14 -4
- data/lib/aspera/json_rpc.rb +49 -0
- data/lib/aspera/keychain/macos_security.rb +13 -13
- data/lib/aspera/line_logger.rb +23 -0
- data/lib/aspera/log.rb +58 -16
- data/lib/aspera/node.rb +157 -92
- data/lib/aspera/oauth.rb +37 -19
- data/lib/aspera/open_application.rb +4 -4
- data/lib/aspera/persistency_action_once.rb +1 -1
- data/lib/aspera/persistency_folder.rb +2 -2
- data/lib/aspera/preview/file_types.rb +4 -2
- data/lib/aspera/preview/generator.rb +22 -35
- data/lib/aspera/preview/options.rb +2 -0
- data/lib/aspera/preview/terminal.rb +73 -16
- data/lib/aspera/preview/utils.rb +21 -28
- data/lib/aspera/proxy_auto_config.js +2 -2
- data/lib/aspera/rest.rb +136 -68
- data/lib/aspera/rest_call_error.rb +1 -1
- data/lib/aspera/rest_error_analyzer.rb +15 -14
- data/lib/aspera/rest_errors_aspera.rb +37 -34
- data/lib/aspera/secret_hider.rb +18 -15
- data/lib/aspera/ssh.rb +5 -2
- data/lib/aspera/sync.rb +127 -119
- data/lib/aspera/temp_file_manager.rb +10 -3
- data/lib/aspera/web_auth.rb +10 -7
- data/lib/aspera/web_server_simple.rb +9 -4
- data.tar.gz.sig +0 -0
- metadata +34 -17
- metadata.gz.sig +0 -0
- data/docs/test_env.conf +0 -186
- data/lib/aspera/cli/listener/line_dump.rb +0 -19
- data/lib/aspera/cli/listener/logger.rb +0 -22
- data/lib/aspera/cli/listener/progress.rb +0 -50
- data/lib/aspera/cli/listener/progress_multi.rb +0 -84
- data/lib/aspera/cli/plugins/sync.rb +0 -44
- data/lib/aspera/data/7 +0 -0
- data/lib/aspera/fasp/listener.rb +0 -13
@@ -1,23 +1,55 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'aspera/cli/
|
3
|
+
require 'aspera/cli/basic_auth_plugin'
|
4
|
+
require 'aspera/nagios'
|
4
5
|
require 'xmlsimple'
|
5
6
|
|
6
7
|
module Aspera
|
7
8
|
module Cli
|
8
9
|
module Plugins
|
9
10
|
class Orchestrator < Aspera::Cli::BasicAuthPlugin
|
11
|
+
class << self
|
12
|
+
STANDARD_PATH = '/aspera/orchestrator'
|
13
|
+
def detect(address_or_url)
|
14
|
+
address_or_url = "https://#{address_or_url}" unless address_or_url.match?(%r{^[a-z]{1,6}://})
|
15
|
+
urls = [address_or_url]
|
16
|
+
urls.push("#{address_or_url}#{STANDARD_PATH}") unless address_or_url.end_with?(STANDARD_PATH)
|
17
|
+
urls.each do |base_url|
|
18
|
+
next unless base_url.match?('https?://')
|
19
|
+
api = Rest.new(base_url: base_url)
|
20
|
+
test_endpoint = 'api/remote_node_ping'
|
21
|
+
result = api.read(test_endpoint, {format: :json})
|
22
|
+
next unless result[:data]['remote_orchestrator_info']
|
23
|
+
url = result[:http].uri.to_s
|
24
|
+
return {
|
25
|
+
version: result[:data]['remote_orchestrator_info']['orchestrator-version'],
|
26
|
+
url: url[0..url.index(test_endpoint) - 2]
|
27
|
+
}
|
28
|
+
rescue StandardError => e
|
29
|
+
Log.log.debug{"detect error: #{e}"}
|
30
|
+
end
|
31
|
+
return nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def wizard(object:, private_key_path: nil, pub_key_pem: nil)
|
35
|
+
options = object.options
|
36
|
+
return {
|
37
|
+
preset_value: {
|
38
|
+
url: options.get_option(:url, mandatory: true),
|
39
|
+
username: options.get_option(:username, mandatory: true),
|
40
|
+
password: options.get_option(:password, mandatory: true)
|
41
|
+
},
|
42
|
+
test_args: 'workflow list'
|
43
|
+
}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
10
47
|
def initialize(env)
|
11
48
|
super(env)
|
12
|
-
options.
|
13
|
-
options.
|
14
|
-
options.
|
15
|
-
options.
|
16
|
-
options.add_opt_list(:auth_style, %i[arg_pass head_basic apikey], 'authentication type')
|
17
|
-
options.set_option(:params, {})
|
18
|
-
options.set_option(:synchronous, :no)
|
19
|
-
options.set_option(:ret_style, :arg)
|
20
|
-
options.set_option(:auth_style, :head_basic)
|
49
|
+
options.declare(:result, "Specify result value as: 'work_step:parameter'")
|
50
|
+
options.declare(:synchronous, 'Wait for completion', values: :bool, default: :no)
|
51
|
+
options.declare(:ret_style, 'How return type is requested in api', values: %i[header arg ext], default: :arg)
|
52
|
+
options.declare(:auth_style, 'Authentication type', values: %i[arg_pass head_basic apikey], default: :head_basic)
|
21
53
|
options.parse_options!
|
22
54
|
end
|
23
55
|
|
@@ -49,7 +81,7 @@ module Aspera
|
|
49
81
|
call_args[:subpath] = "#{opt[:prefix]}/#{call_args[:subpath]}" unless opt[:prefix].nil?
|
50
82
|
# specify id if necessary
|
51
83
|
call_args[:subpath] = "#{call_args[:subpath]}/#{opt[:id]}" if opt.key?(:id)
|
52
|
-
call_type = options.get_option(:ret_style,
|
84
|
+
call_type = options.get_option(:ret_style, mandatory: true)
|
53
85
|
call_type = opt[:ret_style] if opt.key?(:ret_style)
|
54
86
|
format = 'json'
|
55
87
|
format = opt[:format] if opt.key?(:format)
|
@@ -68,24 +100,24 @@ module Aspera
|
|
68
100
|
end
|
69
101
|
result = @api_orch.call(call_args)
|
70
102
|
result[:data] = XmlSimple.xml_in(result[:http].body, opt[:xml_opt] || {'ForceArray' => true}) if format.eql?('xml')
|
71
|
-
Log.dump(:data, result[:data])
|
103
|
+
Log.log.debug{Log.dump(:data, result[:data])}
|
72
104
|
return result
|
73
105
|
end
|
74
106
|
|
75
107
|
def execute_action
|
76
|
-
rest_params = {base_url: options.get_option(:url,
|
77
|
-
case options.get_option(:auth_style,
|
108
|
+
rest_params = {base_url: options.get_option(:url, mandatory: true)}
|
109
|
+
case options.get_option(:auth_style, mandatory: true)
|
78
110
|
when :arg_pass
|
79
111
|
rest_params[:auth] = {
|
80
112
|
type: :url,
|
81
|
-
|
82
|
-
'login' => options.get_option(:username,
|
83
|
-
'password' => options.get_option(:password,
|
113
|
+
url_query: {
|
114
|
+
'login' => options.get_option(:username, mandatory: true),
|
115
|
+
'password' => options.get_option(:password, mandatory: true) }}
|
84
116
|
when :head_basic
|
85
117
|
rest_params[:auth] = {
|
86
118
|
type: :basic,
|
87
|
-
username: options.get_option(:username,
|
88
|
-
password: options.get_option(:password,
|
119
|
+
username: options.get_option(:username, mandatory: true),
|
120
|
+
password: options.get_option(:password, mandatory: true) }
|
89
121
|
when :apikey
|
90
122
|
raise 'Not implemented'
|
91
123
|
end
|
@@ -122,9 +154,9 @@ module Aspera
|
|
122
154
|
end
|
123
155
|
case command
|
124
156
|
when :status
|
125
|
-
|
126
|
-
|
127
|
-
result = call_ao('workflows_status',
|
157
|
+
call_opts = {}
|
158
|
+
call_opts[:id] = wf_id unless wf_id.eql?(ExtendedValue::ALL)
|
159
|
+
result = call_ao('workflows_status', call_opts)[:data]
|
128
160
|
return {type: :object_list, data: result['workflows']['workflow']}
|
129
161
|
when :list
|
130
162
|
result = call_ao('workflows_list', id: 0)[:data]
|
@@ -149,18 +181,18 @@ module Aspera
|
|
149
181
|
}
|
150
182
|
call_params = {format: :json}
|
151
183
|
override_accept = nil
|
152
|
-
#
|
153
|
-
|
184
|
+
# get external parameters if any
|
185
|
+
options.get_next_argument('external_parameters', mandatory: false, type: Hash, default: {}).each do |name, value|
|
154
186
|
call_params["external_parameters[#{name}]"] = value
|
155
187
|
end
|
156
188
|
# synchronous call ?
|
157
|
-
call_params['synchronous'] = true if
|
189
|
+
call_params['synchronous'] = true if options.get_option(:synchronous, mandatory: true)
|
158
190
|
# expected result for synchro call ?
|
159
|
-
|
160
|
-
unless
|
191
|
+
result_location = options.get_option(:result)
|
192
|
+
unless result_location.nil?
|
161
193
|
result[:type] = :status
|
162
|
-
fields =
|
163
|
-
raise "Expects: work_step:result_name
|
194
|
+
fields = result_location.split(':')
|
195
|
+
raise Cli::BadArgument, "Expects: work_step:result_name : #{result_location}" if fields.length != 2
|
164
196
|
call_params['explicit_output_step'] = fields[0]
|
165
197
|
call_params['explicit_output_variable'] = fields[1]
|
166
198
|
# implicitly, call is synchronous
|
@@ -1,17 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# cspell:ignore trevents
|
3
4
|
require 'aspera/cli/basic_auth_plugin'
|
4
5
|
require 'aspera/preview/generator'
|
5
6
|
require 'aspera/preview/options'
|
6
7
|
require 'aspera/preview/utils'
|
7
8
|
require 'aspera/preview/file_types'
|
9
|
+
require 'aspera/preview/terminal'
|
8
10
|
require 'aspera/fasp/transfer_spec'
|
9
11
|
require 'aspera/persistency_action_once'
|
10
12
|
require 'aspera/node'
|
11
13
|
require 'aspera/hash_ext'
|
12
14
|
require 'aspera/timer_limiter'
|
13
15
|
require 'aspera/id_generator'
|
14
|
-
require 'date'
|
15
16
|
require 'securerandom'
|
16
17
|
|
17
18
|
module Aspera
|
@@ -26,8 +27,11 @@ module Aspera
|
|
26
27
|
PREVIEW_BASENAME = 'preview'
|
27
28
|
# subfolder in system tmp folder
|
28
29
|
TMP_DIR_PREFIX = 'prev_tmp'
|
30
|
+
# same value as in aspera.conf
|
29
31
|
DEFAULT_PREVIEWS_FOLDER = 'previews'
|
32
|
+
# mark that this is used by a particular access key
|
30
33
|
AK_MARKER_FILE = '.aspera_access_key'
|
34
|
+
# URL prefix for local storage
|
31
35
|
PVCL_LOCAL_STORAGE = 'file:///'
|
32
36
|
LOG_LIMITER_SEC = 30.0
|
33
37
|
private_constant :PREV_GEN_TAG,
|
@@ -53,44 +57,45 @@ module Aspera
|
|
53
57
|
@gen_options = Aspera::Preview::Options.new
|
54
58
|
# used to trigger periodic processing
|
55
59
|
@periodic = TimerLimiter.new(LOG_LIMITER_SEC)
|
60
|
+
# Proc
|
61
|
+
@filter_block = nil
|
56
62
|
# link CLI options to gen_info attributes
|
57
|
-
options.
|
58
|
-
|
59
|
-
|
60
|
-
options.
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
options.
|
66
|
-
options.
|
67
|
-
options.
|
68
|
-
options.
|
69
|
-
options.
|
70
|
-
options.
|
71
|
-
options.
|
72
|
-
options.
|
73
|
-
options.
|
74
|
-
options.
|
75
|
-
|
76
|
-
|
77
|
-
|
63
|
+
options.declare(
|
64
|
+
:skip_format, 'Skip this preview format (multiple possible)', values: Aspera::Preview::Generator::PREVIEW_FORMATS,
|
65
|
+
handler: {o: self, m: :option_skip_format}, default: [])
|
66
|
+
options.declare(
|
67
|
+
:folder_reset_cache, 'Force detection of generated preview by refresh cache',
|
68
|
+
values: %i[no header read],
|
69
|
+
handler: {o: self, m: :option_folder_reset_cache},
|
70
|
+
default: :no)
|
71
|
+
options.declare(:skip_types, 'Skip types in comma separated list', handler: {o: self, m: :option_skip_types})
|
72
|
+
options.declare(:previews_folder, 'Preview folder in storage root', handler: {o: self, m: :option_previews_folder}, default: DEFAULT_PREVIEWS_FOLDER)
|
73
|
+
options.declare(:temp_folder, 'Path to temp folder', default: Dir.tmpdir)
|
74
|
+
options.declare(:skip_folders, 'List of folder to skip', handler: {o: self, m: :option_skip_folders}, default: [])
|
75
|
+
options.declare(:base, 'Basename of output for for test')
|
76
|
+
options.declare(:scan_path, 'Subpath in folder id to start scan in (default=/)')
|
77
|
+
options.declare(:scan_id, 'Folder id in storage to start scan in, default is access key main folder id')
|
78
|
+
options.declare(:mimemagic, 'Use Mime type detection of gem mimemagic', values: :bool, default: false)
|
79
|
+
options.declare(:overwrite, 'When to overwrite result file', values: %i[always never mtime], handler: {o: self, m: :option_overwrite}, default: :mtime)
|
80
|
+
options.declare(
|
81
|
+
:file_access, 'How to read and write files in repository',
|
82
|
+
values: %i[local remote],
|
83
|
+
handler: {o: self, m: :option_file_access},
|
84
|
+
default: :local)
|
78
85
|
|
79
86
|
# add other options for generator (and set default values)
|
80
87
|
Aspera::Preview::Options::DESCRIPTIONS.each do |opt|
|
81
|
-
|
82
|
-
|
83
|
-
options.add_opt_list(opt[:name], opt[:values], opt[:description])
|
88
|
+
values = if opt.key?(:values)
|
89
|
+
opt[:values]
|
84
90
|
elsif Cli::Manager::BOOLEAN_SIMPLE.include?(opt[:default])
|
85
|
-
|
86
|
-
else
|
87
|
-
options.add_opt_simple(opt[:name], opt[:description])
|
91
|
+
:bool
|
88
92
|
end
|
93
|
+
options.declare(opt[:name], opt[:description].capitalize, values: values, handler: {o: @gen_options, m: opt[:name]}, default: opt[:default])
|
89
94
|
end
|
90
95
|
|
91
96
|
options.parse_options!
|
92
97
|
raise 'skip_folder shall be an Array, use @json:[...]' unless @option_skip_folders.is_a?(Array)
|
93
|
-
@tmp_folder = File.join(options.get_option(:temp_folder,
|
98
|
+
@tmp_folder = File.join(options.get_option(:temp_folder, mandatory: true), "#{TMP_DIR_PREFIX}.#{SecureRandom.uuid}")
|
94
99
|
FileUtils.mkdir_p(@tmp_folder)
|
95
100
|
Log.log.debug{"tmpdir: #{@tmp_folder}"}
|
96
101
|
end
|
@@ -206,34 +211,12 @@ module Aspera
|
|
206
211
|
end
|
207
212
|
|
208
213
|
def do_transfer(direction, folder_id, source_filename, destination='/')
|
209
|
-
raise '
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
template_ts = res[:data]['transfer_specs'].first['transfer_spec']
|
214
|
-
# get ports, anyway that should be 33001 for both. add remote_user ?
|
215
|
-
@default_transfer_spec = %w[ssh_port fasp_port].each_with_object({}){|e, h|h[e] = template_ts[e]; }
|
216
|
-
if !@default_transfer_spec['remote_user'].eql?(Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER)
|
217
|
-
Log.log.warn('remote_user shall be xfer')
|
218
|
-
@default_transfer_spec['remote_user'] = Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER
|
219
|
-
end
|
220
|
-
@api_node.ts_basic_token(@default_transfer_spec)
|
221
|
-
# NOTE: we use the same address for ascp than for node api instead of the one from upload_setup
|
222
|
-
# TODO: configurable ? useful ?
|
223
|
-
@default_transfer_spec['remote_host'] = @transfer_server_address
|
224
|
-
end
|
225
|
-
t_spec = @default_transfer_spec.merge({
|
226
|
-
'direction' => direction,
|
227
|
-
'paths' => [{'source' => source_filename}],
|
228
|
-
'tags' => {
|
229
|
-
Fasp::TransferSpec::TAG_RESERVED => {
|
230
|
-
PREV_GEN_TAG => true,
|
231
|
-
'node' => {
|
232
|
-
'access_key' => @access_key_self['id'],
|
233
|
-
'file_id' => folder_id }}}
|
214
|
+
raise 'Internal ERROR' if destination.nil? && direction.eql?(Fasp::TransferSpec::DIRECTION_RECEIVE)
|
215
|
+
t_spec = @api_node.transfer_spec_gen4(folder_id, direction, {
|
216
|
+
'paths' => [{'source' => source_filename}],
|
217
|
+
'tags' => {Fasp::TransferSpec::TAG_RESERVED => {PREV_GEN_TAG => true}}
|
234
218
|
})
|
235
|
-
# force destination
|
236
|
-
# t_spec['destination_root']=destination
|
219
|
+
# force destination, need to set this in transfer agent else it gets overwritten, not do: t_spec['destination_root']=destination
|
237
220
|
transfer.option_transfer_spec_deep_merge({'destination_root' => destination})
|
238
221
|
Main.result_transfer(transfer.start(t_spec))
|
239
222
|
end
|
@@ -255,6 +238,7 @@ module Aspera
|
|
255
238
|
def get_infos_remote(gen_infos, entry)
|
256
239
|
# store source directly here
|
257
240
|
local_original_filepath = File.join(@tmp_folder, entry['name'])
|
241
|
+
# require 'date'
|
258
242
|
# original_mtime=DateTime.parse(entry['modified_time'])
|
259
243
|
# out: where previews are generated
|
260
244
|
local_entry_preview_dir = File.join(@tmp_folder, entry_preview_folder_name(entry))
|
@@ -278,9 +262,10 @@ module Aspera
|
|
278
262
|
"#{entry['id']}#{PREVIEW_FOLDER_SUFFIX}"
|
279
263
|
end
|
280
264
|
|
281
|
-
|
282
|
-
|
283
|
-
|
265
|
+
# Generate a file name based on basename and format (extension)
|
266
|
+
def preview_filename(preview_format, base_name=nil)
|
267
|
+
base_name ||= PREVIEW_BASENAME
|
268
|
+
return "#{base_name}.#{preview_format}"
|
284
269
|
end
|
285
270
|
|
286
271
|
# generate preview files for one folder entry (file) if necessary
|
@@ -313,10 +298,13 @@ module Aspera
|
|
313
298
|
next false if gen_info[:preview_newer_than_original]
|
314
299
|
end
|
315
300
|
end
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
301
|
+
begin
|
302
|
+
# need generator for further checks
|
303
|
+
gen_info[:generator] = Aspera::Preview::Generator.new(gen_info[:src], gen_info[:dst], @gen_options, @tmp_folder, entry['content_type'])
|
304
|
+
rescue
|
305
|
+
# no conversion supported
|
306
|
+
next false
|
307
|
+
end
|
320
308
|
# shall we skip it ?
|
321
309
|
next false if @skip_types.include?(gen_info[:generator].conversion_type)
|
322
310
|
# ok we need to generate
|
@@ -330,7 +318,7 @@ module Aspera
|
|
330
318
|
# download original file to temp folder
|
331
319
|
do_transfer(Fasp::TransferSpec::DIRECTION_RECEIVE, entry['parent_file_id'], entry['name'], @tmp_folder)
|
332
320
|
end
|
333
|
-
Log.log.info{"source: #{entry['id']}: #{entry['path']}
|
321
|
+
Log.log.info{"source: #{entry['id']}: #{entry['path']}"}
|
334
322
|
gen_infos.each do |gen_info|
|
335
323
|
gen_info[:generator].generate rescue nil
|
336
324
|
end
|
@@ -351,24 +339,22 @@ module Aspera
|
|
351
339
|
end # generate_preview
|
352
340
|
|
353
341
|
# scan all files in provided folder entry
|
354
|
-
# @param
|
355
|
-
def scan_folder_files(top_entry,
|
356
|
-
|
342
|
+
# @param top_path subpath to start folder scan inside
|
343
|
+
def scan_folder_files(top_entry, top_path=nil)
|
344
|
+
unless top_path.nil?
|
357
345
|
# canonical path: start with / and ends with /
|
358
|
-
|
359
|
-
scan_start = "#{scan_start}/" # unless scan_start.end_with?('/')
|
346
|
+
top_path = '/' + top_path.split('/').reject(&:empty?).join('/') + '/'
|
360
347
|
end
|
361
|
-
|
362
|
-
Log.log.debug{"scan: #{top_entry} : #{scan_start}".green}
|
348
|
+
Log.log.debug{"scan: #{top_entry} : #{top_path}".green}
|
363
349
|
# don't use recursive call, use list instead
|
364
350
|
entries_to_process = [top_entry]
|
365
351
|
until entries_to_process.empty?
|
366
352
|
entry = entries_to_process.shift
|
367
|
-
# process this entry only if it is within the
|
353
|
+
# process this entry only if it is within the top_path
|
368
354
|
entry_path_with_slash = entry['path']
|
369
355
|
Log.log.info{"processing entry #{entry_path_with_slash}"} if @periodic.trigger?
|
370
356
|
entry_path_with_slash = "#{entry_path_with_slash}/" unless entry_path_with_slash.end_with?('/')
|
371
|
-
if !
|
357
|
+
if !top_path.nil? && !top_path.start_with?(entry_path_with_slash) && !entry_path_with_slash.start_with?(top_path)
|
372
358
|
Log.log.debug{"#{entry['path']} folder (skip start)".bg_red}
|
373
359
|
next
|
374
360
|
end
|
@@ -376,7 +362,7 @@ module Aspera
|
|
376
362
|
begin
|
377
363
|
case entry['type']
|
378
364
|
when 'file'
|
379
|
-
if filter_block.call(entry)
|
365
|
+
if @filter_block.call(entry)
|
380
366
|
generate_preview(entry)
|
381
367
|
else
|
382
368
|
Log.log.debug('skip by filter')
|
@@ -409,11 +395,11 @@ module Aspera
|
|
409
395
|
end
|
410
396
|
end
|
411
397
|
|
412
|
-
ACTIONS = %i[scan events trevents check test].freeze
|
398
|
+
ACTIONS = %i[scan events trevents check test show].freeze
|
413
399
|
|
414
400
|
def execute_action
|
415
401
|
command = options.get_next_command(ACTIONS)
|
416
|
-
unless %i[check test].include?(command)
|
402
|
+
unless %i[check test show].include?(command)
|
417
403
|
# this will use node api
|
418
404
|
@api_node = Aspera::Node.new(params: basic_auth_params)
|
419
405
|
@transfer_server_address = URI.parse(@api_node.params[:base_url]).host
|
@@ -431,7 +417,7 @@ module Aspera
|
|
431
417
|
if @access_remote
|
432
418
|
# NOTE: the filter "name", it's why we take the first one
|
433
419
|
@previews_folder_entry = get_folder_entries(@access_key_self['root_file_id'], {name: @option_previews_folder}).first
|
434
|
-
raise
|
420
|
+
raise Cli::Error, "Folder #{@option_previews_folder} does not exist on node. " \
|
435
421
|
'Please create it in the storage root, or specify an alternate name.' if @previews_folder_entry.nil?
|
436
422
|
else
|
437
423
|
raise 'only local storage allowed in this mode' unless @access_key_self['storage']['type'].eql?('local')
|
@@ -440,9 +426,9 @@ module Aspera
|
|
440
426
|
@local_storage_root = @local_storage_root[PVCL_LOCAL_STORAGE.length..-1] if @local_storage_root.start_with?(PVCL_LOCAL_STORAGE)
|
441
427
|
# TODO: windows could have "C:" ?
|
442
428
|
raise "not local storage: #{@local_storage_root}" unless @local_storage_root.start_with?('/')
|
443
|
-
raise
|
429
|
+
raise Cli::Error, "Local storage root folder #{@local_storage_root} does not exist." unless File.directory?(@local_storage_root)
|
444
430
|
@local_preview_folder = File.join(@local_storage_root, @option_previews_folder)
|
445
|
-
raise
|
431
|
+
raise Cli::Error, "Folder #{@local_preview_folder} does not exist locally. " \
|
446
432
|
'Please create it, or specify an alternate name.' unless File.directory?(@local_preview_folder)
|
447
433
|
# protection to avoid clash of file id for two different access keys
|
448
434
|
marker_file = File.join(@local_preview_folder, AK_MARKER_FILE)
|
@@ -455,7 +441,7 @@ module Aspera
|
|
455
441
|
end
|
456
442
|
end
|
457
443
|
end
|
458
|
-
Aspera::Preview::FileTypes.instance.use_mimemagic = options.get_option(:mimemagic,
|
444
|
+
Aspera::Preview::FileTypes.instance.use_mimemagic = options.get_option(:mimemagic, mandatory: true)
|
459
445
|
# check tools that are anyway required for all cases
|
460
446
|
Aspera::Preview::Utils.check_tools(@skip_types)
|
461
447
|
case command
|
@@ -473,19 +459,21 @@ module Aspera
|
|
473
459
|
else
|
474
460
|
@api_node.read("files/#{scan_id}")[:data]
|
475
461
|
end
|
462
|
+
@filter_block = Aspera::Node.file_matcher_from_argument(options)
|
476
463
|
scan_folder_files(folder_info, scan_path)
|
477
464
|
return Main.result_status('scan finished')
|
478
465
|
when :events, :trevents
|
466
|
+
@filter_block = Aspera::Node.file_matcher_from_argument(options)
|
479
467
|
iteration_persistency = nil
|
480
|
-
if options.get_option(:once_only,
|
468
|
+
if options.get_option(:once_only, mandatory: true)
|
481
469
|
iteration_persistency = PersistencyActionOnce.new(
|
482
470
|
manager: @agents[:persistency],
|
483
471
|
data: [],
|
484
472
|
id: IdGenerator.from_list([
|
485
473
|
'preview_iteration',
|
486
474
|
command.to_s,
|
487
|
-
options.get_option(:url,
|
488
|
-
options.get_option(:username,
|
475
|
+
options.get_option(:url, mandatory: true),
|
476
|
+
options.get_option(:username, mandatory: true)
|
489
477
|
]))
|
490
478
|
end
|
491
479
|
# call processing method specified by command line command
|
@@ -493,19 +481,23 @@ module Aspera
|
|
493
481
|
return Main.result_status("#{command} finished")
|
494
482
|
when :check
|
495
483
|
return Main.result_status('Tools validated')
|
496
|
-
when :test
|
497
|
-
format = options.get_next_argument('format', expected: Aspera::Preview::Generator::PREVIEW_FORMATS)
|
484
|
+
when :test, :show
|
498
485
|
source = options.get_next_argument('source file')
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
raise "out format #{format} not supported" unless g.supported?
|
486
|
+
format = options.get_next_argument('format', expected: Aspera::Preview::Generator::PREVIEW_FORMATS, default: :png)
|
487
|
+
generated_file_path = preview_filename(format, options.get_option(:base))
|
488
|
+
g = Aspera::Preview::Generator.new(source, generated_file_path, @gen_options, @tmp_folder, nil)
|
503
489
|
g.generate
|
504
|
-
|
490
|
+
if command.eql?(:show)
|
491
|
+
terminal_options = options.get_option(:query, default: {}).symbolize_keys
|
492
|
+
Log.log.debug{"preview: #{generated_file_path}"}
|
493
|
+
formatter.display_status(Aspera::Preview::Terminal.build(File.read(generated_file_path), **terminal_options))
|
494
|
+
end
|
495
|
+
return Main.result_status("generated: #{generated_file_path}")
|
505
496
|
else
|
506
497
|
raise 'error'
|
507
498
|
end
|
508
499
|
ensure
|
500
|
+
Log.log.debug{"cleaning up temp folder #{@tmp_folder}"}
|
509
501
|
FileUtils.rm_rf(@tmp_folder)
|
510
502
|
end # execute_action
|
511
503
|
end # Preview
|