aspera-cli 4.12.0 → 4.14.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 +45 -5
- data/CONTRIBUTING.md +113 -22
- data/README.md +1289 -754
- data/bin/ascli +3 -3
- data/examples/dascli +1 -1
- data/examples/rubyc +24 -0
- data/lib/aspera/aoc.rb +63 -74
- data/lib/aspera/ascmd.rb +5 -3
- data/lib/aspera/cli/basic_auth_plugin.rb +6 -6
- data/lib/aspera/cli/extended_value.rb +24 -37
- data/lib/aspera/cli/formatter.rb +23 -25
- data/lib/aspera/cli/info.rb +2 -4
- data/lib/aspera/cli/main.rb +27 -27
- data/lib/aspera/cli/manager.rb +143 -120
- data/lib/aspera/cli/plugin.rb +88 -43
- data/lib/aspera/cli/plugins/alee.rb +2 -2
- data/lib/aspera/cli/plugins/aoc.rb +235 -104
- data/lib/aspera/cli/plugins/ats.rb +16 -18
- data/lib/aspera/cli/plugins/bss.rb +3 -3
- data/lib/aspera/cli/plugins/config.rb +190 -373
- data/lib/aspera/cli/plugins/console.rb +4 -6
- data/lib/aspera/cli/plugins/cos.rb +12 -13
- data/lib/aspera/cli/plugins/faspex.rb +21 -21
- data/lib/aspera/cli/plugins/faspex5.rb +399 -150
- data/lib/aspera/cli/plugins/node.rb +260 -174
- data/lib/aspera/cli/plugins/orchestrator.rb +15 -18
- data/lib/aspera/cli/plugins/preview.rb +40 -62
- data/lib/aspera/cli/plugins/server.rb +33 -16
- data/lib/aspera/cli/plugins/shares.rb +24 -33
- data/lib/aspera/cli/plugins/sync.rb +6 -6
- data/lib/aspera/cli/transfer_agent.rb +47 -30
- data/lib/aspera/cli/version.rb +2 -1
- data/lib/aspera/colors.rb +9 -7
- data/lib/aspera/command_line_builder.rb +2 -1
- data/lib/aspera/cos_node.rb +1 -1
- data/lib/aspera/data/6 +0 -0
- data/lib/aspera/environment.rb +7 -3
- data/lib/aspera/fasp/agent_connect.rb +6 -1
- data/lib/aspera/fasp/agent_direct.rb +17 -17
- data/lib/aspera/fasp/agent_httpgw.rb +138 -60
- data/lib/aspera/fasp/agent_node.rb +14 -4
- data/lib/aspera/fasp/agent_trsdk.rb +2 -0
- data/lib/aspera/fasp/error_info.rb +2 -0
- data/lib/aspera/fasp/installation.rb +19 -19
- data/lib/aspera/fasp/parameters.rb +29 -20
- data/lib/aspera/fasp/parameters.yaml +5 -2
- data/lib/aspera/fasp/resume_policy.rb +3 -3
- data/lib/aspera/fasp/transfer_spec.rb +8 -5
- data/lib/aspera/fasp/uri.rb +23 -21
- data/lib/aspera/faspex_gw.rb +1 -0
- data/lib/aspera/faspex_postproc.rb +3 -3
- data/lib/aspera/hash_ext.rb +12 -2
- data/lib/aspera/keychain/macos_security.rb +13 -13
- data/lib/aspera/log.rb +1 -0
- data/lib/aspera/node.rb +73 -84
- data/lib/aspera/oauth.rb +4 -3
- data/lib/aspera/persistency_action_once.rb +1 -1
- data/lib/aspera/preview/file_types.rb +8 -6
- data/lib/aspera/preview/generator.rb +23 -11
- data/lib/aspera/preview/options.rb +3 -2
- data/lib/aspera/preview/terminal.rb +80 -0
- data/lib/aspera/preview/utils.rb +11 -11
- data/lib/aspera/proxy_auto_config.js +2 -2
- data/lib/aspera/rest.rb +42 -4
- data/lib/aspera/rest_call_error.rb +3 -1
- data/lib/aspera/secret_hider.rb +10 -5
- data/lib/aspera/ssh.rb +1 -1
- data/lib/aspera/sync.rb +41 -33
- data/lib/aspera/web_server_simple.rb +22 -18
- data.tar.gz.sig +0 -0
- metadata +40 -48
- metadata.gz.sig +0 -0
- data/docs/test_env.conf +0 -179
- data/examples/aoc.rb +0 -30
- data/examples/faspex4.rb +0 -94
- data/examples/node.rb +0 -96
- data/examples/server.rb +0 -93
- data/lib/aspera/data/7 +0 -0
@@ -9,15 +9,11 @@ module Aspera
|
|
9
9
|
class Orchestrator < Aspera::Cli::BasicAuthPlugin
|
10
10
|
def initialize(env)
|
11
11
|
super(env)
|
12
|
-
options.
|
13
|
-
options.
|
14
|
-
options.
|
15
|
-
options.
|
16
|
-
options.
|
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)
|
12
|
+
options.declare(:params, 'Start parameters', types: Hash, default: {})
|
13
|
+
options.declare(:result, "Specify result value as: 'work step:parameter'")
|
14
|
+
options.declare(:synchronous, 'Work step:parameter expected as result', values: :bool, default: :no)
|
15
|
+
options.declare(:ret_style, 'How return type is requested in api', values: %i[header arg ext], default: :arg)
|
16
|
+
options.declare(:auth_style, 'Authentication type', values: %i[arg_pass head_basic apikey], default: :head_basic)
|
21
17
|
options.parse_options!
|
22
18
|
end
|
23
19
|
|
@@ -49,7 +45,7 @@ module Aspera
|
|
49
45
|
call_args[:subpath] = "#{opt[:prefix]}/#{call_args[:subpath]}" unless opt[:prefix].nil?
|
50
46
|
# specify id if necessary
|
51
47
|
call_args[:subpath] = "#{call_args[:subpath]}/#{opt[:id]}" if opt.key?(:id)
|
52
|
-
call_type = options.get_option(:ret_style,
|
48
|
+
call_type = options.get_option(:ret_style, mandatory: true)
|
53
49
|
call_type = opt[:ret_style] if opt.key?(:ret_style)
|
54
50
|
format = 'json'
|
55
51
|
format = opt[:format] if opt.key?(:format)
|
@@ -73,19 +69,19 @@ module Aspera
|
|
73
69
|
end
|
74
70
|
|
75
71
|
def execute_action
|
76
|
-
rest_params = {base_url: options.get_option(:url,
|
77
|
-
case options.get_option(:auth_style,
|
72
|
+
rest_params = {base_url: options.get_option(:url, mandatory: true)}
|
73
|
+
case options.get_option(:auth_style, mandatory: true)
|
78
74
|
when :arg_pass
|
79
75
|
rest_params[:auth] = {
|
80
76
|
type: :url,
|
81
77
|
url_creds: {
|
82
|
-
'login' => options.get_option(:username,
|
83
|
-
'password' => options.get_option(:password,
|
78
|
+
'login' => options.get_option(:username, mandatory: true),
|
79
|
+
'password' => options.get_option(:password, mandatory: true) }}
|
84
80
|
when :head_basic
|
85
81
|
rest_params[:auth] = {
|
86
82
|
type: :basic,
|
87
|
-
username: options.get_option(:username,
|
88
|
-
password: options.get_option(:password,
|
83
|
+
username: options.get_option(:username, mandatory: true),
|
84
|
+
password: options.get_option(:password, mandatory: true) }
|
89
85
|
when :apikey
|
90
86
|
raise 'Not implemented'
|
91
87
|
end
|
@@ -150,11 +146,12 @@ module Aspera
|
|
150
146
|
call_params = {format: :json}
|
151
147
|
override_accept = nil
|
152
148
|
# set external parameters if any
|
153
|
-
|
149
|
+
# TODO: make not an option, but a parameter
|
150
|
+
self.options.get_option(:params, mandatory: true).each do |name, value|
|
154
151
|
call_params["external_parameters[#{name}]"] = value
|
155
152
|
end
|
156
153
|
# synchronous call ?
|
157
|
-
call_params['synchronous'] = true if self.options.get_option(:synchronous,
|
154
|
+
call_params['synchronous'] = true if self.options.get_option(:synchronous, mandatory: true)
|
158
155
|
# expected result for synchro call ?
|
159
156
|
expected = self.options.get_option(:result)
|
160
157
|
unless expected.nil?
|
@@ -54,43 +54,42 @@ module Aspera
|
|
54
54
|
# used to trigger periodic processing
|
55
55
|
@periodic = TimerLimiter.new(LOG_LIMITER_SEC)
|
56
56
|
# 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
|
-
|
57
|
+
options.declare(
|
58
|
+
:skip_format, 'Skip this preview format (multiple possible)', values: Aspera::Preview::Generator::PREVIEW_FORMATS,
|
59
|
+
handler: {o: self, m: :option_skip_format}, default: [])
|
60
|
+
options.declare(
|
61
|
+
:folder_reset_cache, 'Force detection of generated preview by refresh cache',
|
62
|
+
values: %i[no header read],
|
63
|
+
handler: {o: self, m: :option_folder_reset_cache},
|
64
|
+
default: :no)
|
65
|
+
options.declare(:skip_types, 'Skip types in comma separated list', handler: {o: self, m: :option_skip_types})
|
66
|
+
options.declare(:previews_folder, 'Preview folder in storage root', handler: {o: self, m: :option_previews_folder}, default: DEFAULT_PREVIEWS_FOLDER)
|
67
|
+
options.declare(:temp_folder, 'Path to temp folder', default: Dir.tmpdir)
|
68
|
+
options.declare(:skip_folders, 'List of folder to skip', handler: {o: self, m: :option_skip_folders}, default: [])
|
69
|
+
options.declare(:case, 'Basename of output for for test')
|
70
|
+
options.declare(:scan_path, 'Subpath in folder id to start scan in (default=/)')
|
71
|
+
options.declare(:scan_id, 'Folder id in storage to start scan in, default is access key main folder id')
|
72
|
+
options.declare(:mimemagic, 'Use Mime type detection of gem mimemagic', values: :bool, default: false)
|
73
|
+
options.declare(:overwrite, 'When to overwrite result file', values: %i[always never mtime], handler: {o: self, m: :option_overwrite}, default: :mtime)
|
74
|
+
options.declare(
|
75
|
+
:file_access, 'How to read and write files in repository',
|
76
|
+
values: %i[local remote],
|
77
|
+
handler: {o: self, m: :option_file_access},
|
78
|
+
default: :local)
|
78
79
|
|
79
80
|
# add other options for generator (and set default values)
|
80
81
|
Aspera::Preview::Options::DESCRIPTIONS.each do |opt|
|
81
|
-
|
82
|
-
|
83
|
-
options.add_opt_list(opt[:name], opt[:values], opt[:description])
|
82
|
+
values = if opt.key?(:values)
|
83
|
+
opt[:values]
|
84
84
|
elsif Cli::Manager::BOOLEAN_SIMPLE.include?(opt[:default])
|
85
|
-
|
86
|
-
else
|
87
|
-
options.add_opt_simple(opt[:name], opt[:description])
|
85
|
+
:bool
|
88
86
|
end
|
87
|
+
options.declare(opt[:name], opt[:description].capitalize, values: values, handler: {o: @gen_options, m: opt[:name]}, default: opt[:default])
|
89
88
|
end
|
90
89
|
|
91
90
|
options.parse_options!
|
92
91
|
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,
|
92
|
+
@tmp_folder = File.join(options.get_option(:temp_folder, mandatory: true), "#{TMP_DIR_PREFIX}.#{SecureRandom.uuid}")
|
94
93
|
FileUtils.mkdir_p(@tmp_folder)
|
95
94
|
Log.log.debug{"tmpdir: #{@tmp_folder}"}
|
96
95
|
end
|
@@ -149,8 +148,8 @@ module Aspera
|
|
149
148
|
if event['data']['direction'].eql?(Fasp::TransferSpec::DIRECTION_RECEIVE) &&
|
150
149
|
event['data']['status'].eql?('completed') &&
|
151
150
|
event['data']['error_code'].eql?(0) &&
|
152
|
-
event['data'].dig('tags',
|
153
|
-
folder_id = event.dig('data', 'tags',
|
151
|
+
event['data'].dig('tags', Fasp::TransferSpec::TAG_RESERVED, PREV_GEN_TAG).nil?
|
152
|
+
folder_id = event.dig('data', 'tags', Fasp::TransferSpec::TAG_RESERVED, 'node', 'file_id')
|
154
153
|
folder_id ||= event.dig('data', 'file_id')
|
155
154
|
if !folder_id.nil?
|
156
155
|
folder_entry = @api_node.read("files/#{folder_id}")[:data] rescue nil
|
@@ -206,34 +205,12 @@ module Aspera
|
|
206
205
|
end
|
207
206
|
|
208
207
|
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
|
-
'aspera' => {
|
230
|
-
PREV_GEN_TAG => true,
|
231
|
-
'node' => {
|
232
|
-
'access_key' => @access_key_self['id'],
|
233
|
-
'file_id' => folder_id }}}
|
208
|
+
raise 'Internal ERROR' if destination.nil? && direction.eql?(Fasp::TransferSpec::DIRECTION_RECEIVE)
|
209
|
+
t_spec = @api_node.transfer_spec_gen4(folder_id, direction, {
|
210
|
+
'paths' => [{'source' => source_filename}],
|
211
|
+
'tags' => {Fasp::TransferSpec::TAG_RESERVED => {PREV_GEN_TAG => true}}
|
234
212
|
})
|
235
|
-
# force destination
|
236
|
-
# t_spec['destination_root']=destination
|
213
|
+
# force destination, need to set this in transfer agent else it gets overwritten, not do: t_spec['destination_root']=destination
|
237
214
|
transfer.option_transfer_spec_deep_merge({'destination_root' => destination})
|
238
215
|
Main.result_transfer(transfer.start(t_spec))
|
239
216
|
end
|
@@ -358,7 +335,7 @@ module Aspera
|
|
358
335
|
scan_start = '/' + scan_start.split('/').reject(&:empty?).join('/')
|
359
336
|
scan_start = "#{scan_start}/" # unless scan_start.end_with?('/')
|
360
337
|
end
|
361
|
-
filter_block = Aspera::Node.file_matcher(
|
338
|
+
filter_block = Aspera::Node.file_matcher(value_or_query(allowed_types: String))
|
362
339
|
Log.log.debug{"scan: #{top_entry} : #{scan_start}".green}
|
363
340
|
# don't use recursive call, use list instead
|
364
341
|
entries_to_process = [top_entry]
|
@@ -455,7 +432,7 @@ module Aspera
|
|
455
432
|
end
|
456
433
|
end
|
457
434
|
end
|
458
|
-
Aspera::Preview::FileTypes.instance.use_mimemagic = options.get_option(:mimemagic,
|
435
|
+
Aspera::Preview::FileTypes.instance.use_mimemagic = options.get_option(:mimemagic, mandatory: true)
|
459
436
|
# check tools that are anyway required for all cases
|
460
437
|
Aspera::Preview::Utils.check_tools(@skip_types)
|
461
438
|
case command
|
@@ -477,15 +454,15 @@ module Aspera
|
|
477
454
|
return Main.result_status('scan finished')
|
478
455
|
when :events, :trevents
|
479
456
|
iteration_persistency = nil
|
480
|
-
if options.get_option(:once_only,
|
457
|
+
if options.get_option(:once_only, mandatory: true)
|
481
458
|
iteration_persistency = PersistencyActionOnce.new(
|
482
459
|
manager: @agents[:persistency],
|
483
460
|
data: [],
|
484
461
|
id: IdGenerator.from_list([
|
485
462
|
'preview_iteration',
|
486
463
|
command.to_s,
|
487
|
-
options.get_option(:url,
|
488
|
-
options.get_option(:username,
|
464
|
+
options.get_option(:url, mandatory: true),
|
465
|
+
options.get_option(:username, mandatory: true)
|
489
466
|
]))
|
490
467
|
end
|
491
468
|
# call processing method specified by command line command
|
@@ -506,6 +483,7 @@ module Aspera
|
|
506
483
|
raise 'error'
|
507
484
|
end
|
508
485
|
ensure
|
486
|
+
Log.log.debug{"cleaning up temp folder #{@tmp_folder}"}
|
509
487
|
FileUtils.rm_rf(@tmp_folder)
|
510
488
|
end # execute_action
|
511
489
|
end # Preview
|
@@ -13,9 +13,21 @@ module Aspera
|
|
13
13
|
module Cli
|
14
14
|
module Plugins
|
15
15
|
# implement basic remote access with FASP/SSH
|
16
|
+
class SyncSpecServer
|
17
|
+
def initialize(transfer_spec)
|
18
|
+
@transfer_spec = transfer_spec
|
19
|
+
end
|
20
|
+
|
21
|
+
def transfer_spec(direction, local_path, remote_path)
|
22
|
+
return @transfer_spec
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
16
26
|
class Server < Aspera::Cli::BasicAuthPlugin
|
17
27
|
SSH_SCHEME = 'ssh'
|
18
|
-
|
28
|
+
LOCAL_SCHEME = 'local'
|
29
|
+
HTTPS_SCHEME = 'https'
|
30
|
+
URI_SCHEMES = [SSH_SCHEME, LOCAL_SCHEME, HTTPS_SCHEME].freeze
|
19
31
|
ASCMD_ALIASES = {
|
20
32
|
browse: :ls,
|
21
33
|
delete: :rm,
|
@@ -31,7 +43,7 @@ module Aspera
|
|
31
43
|
cmd = cmd.map{|v|%Q("#{v}")}.join(' ') if cmd.is_a?(Array)
|
32
44
|
Log.log.debug{"Executing: #{cmd} with '#{line}'"}
|
33
45
|
stdout_str, stderr_str, status = Open3.capture3(cmd, stdin_data: line, binmode: true)
|
34
|
-
Log.log.debug
|
46
|
+
Log.log.debug{"exec status: #{status} -> #{stderr_str}"}
|
35
47
|
raise "command #{cmd} failed with code #{status.exitstatus} #{stderr_str}" unless status.success?
|
36
48
|
return stdout_str
|
37
49
|
end
|
@@ -39,28 +51,32 @@ module Aspera
|
|
39
51
|
|
40
52
|
def initialize(env)
|
41
53
|
super(env)
|
42
|
-
options.
|
43
|
-
options.
|
54
|
+
options.declare(:ssh_keys, 'SSH key path list (Array or single)')
|
55
|
+
options.declare(:passphrase, 'SSH private key passphrase')
|
56
|
+
options.declare(:ssh_options, 'SSH options', types: Hash, default: {})
|
44
57
|
options.parse_options!
|
45
|
-
@ssh_opts =
|
58
|
+
@ssh_opts = options.get_option(:ssh_options).symbolize_keys
|
46
59
|
end
|
47
60
|
|
48
61
|
# Read command line options
|
49
62
|
# @return [Hash] transfer specification
|
50
63
|
def options_to_base_transfer_spec
|
51
|
-
url = options.get_option(:url,
|
64
|
+
url = options.get_option(:url, mandatory: true)
|
52
65
|
server_transfer_spec = {}
|
53
66
|
server_uri = URI.parse(url)
|
54
|
-
Log.log.debug{"URI
|
67
|
+
Log.log.debug{"URI=#{server_uri}, host=#{server_uri.hostname}, port=#{server_uri.port}, scheme=#{server_uri.scheme}"}
|
55
68
|
server_transfer_spec['remote_host'] = server_uri.hostname
|
56
69
|
unless URI_SCHEMES.include?(server_uri.scheme)
|
57
70
|
Log.log.warn{"Scheme [#{server_uri.scheme}] not supported in #{url}, use one of: #{URI_SCHEMES.join(', ')}. Defaulting to #{SSH_SCHEME}."}
|
58
71
|
server_uri.scheme = SSH_SCHEME
|
59
72
|
end
|
60
|
-
if server_uri.scheme.eql?(
|
73
|
+
if server_uri.scheme.eql?(LOCAL_SCHEME)
|
61
74
|
# Using local execution (mostly for testing)
|
75
|
+
server_transfer_spec['remote_host'] = 'localhost'
|
76
|
+
# simulate SSH environment, else ascp will fail
|
77
|
+
ENV['SSH_CLIENT'] = 'local 0 0'
|
62
78
|
return server_transfer_spec
|
63
|
-
elsif transfer.option_transfer_spec['token'].is_a?(String) && server_uri.scheme.eql?(
|
79
|
+
elsif transfer.option_transfer_spec['token'].is_a?(String) && server_uri.scheme.eql?(HTTPS_SCHEME)
|
64
80
|
server_transfer_spec['wss_enabled'] = true
|
65
81
|
server_transfer_spec['wss_port'] = server_uri.port
|
66
82
|
# Using WSS
|
@@ -78,11 +94,7 @@ module Aspera
|
|
78
94
|
options.set_option(:username, Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER)
|
79
95
|
Log.log.info{"No username provided: Assuming default transfer user: #{Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER}"}
|
80
96
|
end
|
81
|
-
server_transfer_spec['remote_user'] = options.get_option(:username,
|
82
|
-
ssh_args = options.get_option(:ssh_options)
|
83
|
-
ssh_args = {} if ssh_args.nil?
|
84
|
-
raise 'expecting a Hash for ssh_options' unless ssh_args.is_a?(Hash)
|
85
|
-
@ssh_opts = ssh_args.symbolize_keys
|
97
|
+
server_transfer_spec['remote_user'] = options.get_option(:username, mandatory: true)
|
86
98
|
if !server_uri.port.nil?
|
87
99
|
@ssh_opts[:port] = server_uri.port
|
88
100
|
server_transfer_spec['ssh_port'] = server_uri.port
|
@@ -109,6 +121,11 @@ module Aspera
|
|
109
121
|
cred_set = true
|
110
122
|
end
|
111
123
|
end
|
124
|
+
ssh_passphrase = options.get_option(:passphrase)
|
125
|
+
if !ssh_passphrase.nil?
|
126
|
+
@ssh_opts[:passphrase] = ssh_passphrase
|
127
|
+
server_transfer_spec['ssh_private_key_passphrase'] = ssh_passphrase
|
128
|
+
end
|
112
129
|
# if user provided transfer spec has a token, we will use bypass keys
|
113
130
|
cred_set = true if transfer.option_transfer_spec['token'].is_a?(String)
|
114
131
|
raise 'Either password, key , or transfer spec token must be provided' if !cred_set
|
@@ -121,7 +138,7 @@ module Aspera
|
|
121
138
|
Fasp::TransferSpec.action_to_direction(transfer_spec, command)
|
122
139
|
return Main.result_transfer(transfer.start(transfer_spec))
|
123
140
|
when :sync
|
124
|
-
sync_plugin = Sync.new(@agents,
|
141
|
+
sync_plugin = Plugins::Sync.new(@agents, sync_spec: SyncSpecServer.new(transfer_spec))
|
125
142
|
return sync_plugin.execute_action
|
126
143
|
end
|
127
144
|
end
|
@@ -133,7 +150,7 @@ module Aspera
|
|
133
150
|
|
134
151
|
def execute_action
|
135
152
|
server_transfer_spec = options_to_base_transfer_spec
|
136
|
-
ascmd_executor = if !@ssh_opts.
|
153
|
+
ascmd_executor = if !@ssh_opts.empty?
|
137
154
|
Ssh.new(server_transfer_spec['remote_host'], server_transfer_spec['remote_user'], @ssh_opts)
|
138
155
|
elsif server_transfer_spec.key?('wss_enabled')
|
139
156
|
nil
|
@@ -26,24 +26,25 @@ module Aspera
|
|
26
26
|
|
27
27
|
def initialize(env)
|
28
28
|
super(env)
|
29
|
-
options.
|
30
|
-
options.set_option(:type, :any)
|
29
|
+
options.declare(:type, 'Type of user/group for operations', values: %i[any local ldap saml], default: :any)
|
31
30
|
options.parse_options!
|
32
31
|
end
|
33
32
|
|
34
33
|
SAML_IMPORT_MANDATORY = %w[id name_id].freeze
|
35
34
|
SAML_IMPORT_ALLOWED = %w[email given_name surname].concat(SAML_IMPORT_MANDATORY).freeze
|
36
35
|
|
37
|
-
ACTIONS = %i[health
|
36
|
+
ACTIONS = %i[health files admin].freeze
|
37
|
+
# common to users and groups
|
38
|
+
USR_GRP_SETTINGS = %i[transfer_settings app_authorizations share_permissions].freeze
|
38
39
|
|
39
40
|
def execute_action
|
40
|
-
command = options.get_next_command(ACTIONS)
|
41
|
+
command = options.get_next_command(ACTIONS, aliases: {repository: :files})
|
41
42
|
case command
|
42
43
|
when :health
|
43
44
|
nagios = Nagios.new
|
44
45
|
begin
|
45
46
|
Rest
|
46
|
-
.new(base_url: options.get_option(:url,
|
47
|
+
.new(base_url: options.get_option(:url, mandatory: true) + '/node_api')
|
47
48
|
.call(
|
48
49
|
operation: 'GET',
|
49
50
|
subpath: 'ping',
|
@@ -54,25 +55,28 @@ module Aspera
|
|
54
55
|
nagios.add_critical('node api', e.to_s)
|
55
56
|
end
|
56
57
|
return nagios.result
|
57
|
-
when :repository
|
58
|
+
when :repository, :files
|
58
59
|
api_shares_node = basic_auth_api('node_api')
|
59
60
|
repo_command = options.get_next_command(Node::COMMANDS_SHARES)
|
60
61
|
return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_shares_node)).execute_action(repo_command)
|
61
62
|
when :admin
|
62
63
|
api_shares_admin = basic_auth_api('api/v1')
|
63
|
-
admin_command = options.get_next_command(%i[user group share node])
|
64
|
+
admin_command = options.get_next_command(%i[user group share node].freeze)
|
64
65
|
case admin_command
|
65
66
|
when :node
|
66
67
|
return entity_action(api_shares_admin, 'data/nodes')
|
67
68
|
when :user, :group
|
68
69
|
entity_type = admin_command
|
69
|
-
entities_location = options.get_option(:type,
|
70
|
+
entities_location = options.get_option(:type, mandatory: true)
|
70
71
|
entities_path = "data/#{entities_location}_#{entity_type}s"
|
71
72
|
entity_action = nil
|
72
73
|
case entities_location
|
73
74
|
when :any
|
74
75
|
entities_path = "data/#{entity_type}s"
|
75
|
-
entity_action = %i[list show delete
|
76
|
+
entity_action = %i[list show delete]
|
77
|
+
entity_action.concat(USR_GRP_SETTINGS)
|
78
|
+
entity_action.push(:users) if entity_type.eql?(:group)
|
79
|
+
entity_action.freeze
|
76
80
|
when :local
|
77
81
|
entity_action = %i[list show create modify delete].freeze
|
78
82
|
when :ldap
|
@@ -80,31 +84,15 @@ module Aspera
|
|
80
84
|
when :saml
|
81
85
|
entity_action = %i[import].freeze
|
82
86
|
end
|
83
|
-
|
84
|
-
entity_path = "#{entities_path}/#{instance_identifier}" if %i[app_authorizations share_permissions].include?(
|
85
|
-
case
|
86
|
-
when
|
87
|
+
entity_verb = options.get_next_command(entity_action)
|
88
|
+
# entity_path = "#{entities_path}/#{instance_identifier}" if %i[app_authorizations share_permissions].include?(entity_verb)
|
89
|
+
case entity_verb
|
90
|
+
when *Plugin::ALL_OPS
|
87
91
|
display_fields = entity_type.eql?(:user) ? %w[id username first_name last_name email] : nil
|
88
92
|
display_fields.push(:directory_user) if entity_type.eql?(:user) && entities_location.eql?(:any)
|
89
|
-
return entity_command(
|
90
|
-
when :app_authorizations
|
91
|
-
case options.get_next_command(%i[modify show])
|
92
|
-
when :show
|
93
|
-
return {type: :single_object, data: api_shares_admin.read("#{entity_path}/app_authorizations")[:data]}
|
94
|
-
when :modify
|
95
|
-
parameters = options.get_option(:value, is_type: :mandatory)
|
96
|
-
return {type: :single_object, data: api_shares_admin.update("#{entity_path}/app_authorizations", parameters)[:data]}
|
97
|
-
end
|
98
|
-
when :share_permissions
|
99
|
-
case options.get_next_command(%i[list show])
|
100
|
-
when :list
|
101
|
-
return {type: :object_list, data: api_shares_admin.read("#{entity_path}/share_permissions")[:data]}
|
102
|
-
when :show
|
103
|
-
return {type: :single_object, data: api_shares_admin.read("#{entity_path}/share_permissions/#{instance_identifier}")[:data]}
|
104
|
-
end
|
93
|
+
return entity_command(entity_verb, api_shares_admin, entities_path, display_fields: display_fields)
|
105
94
|
when :import
|
106
|
-
|
107
|
-
return do_bulk_operation(parameters, 'created') do |entity_parameters|
|
95
|
+
return do_bulk_operation(value_create_modify(type: :bulk_hash), 'created') do |entity_parameters|
|
108
96
|
entity_parameters = entity_parameters.transform_keys{|k|k.gsub(/\s+/, '_').downcase}
|
109
97
|
raise 'expecting Hash' unless entity_parameters.is_a?(Hash)
|
110
98
|
SAML_IMPORT_MANDATORY.each{|p|raise "missing mandatory field: #{p}" if entity_parameters[p].nil?}
|
@@ -114,11 +102,14 @@ module Aspera
|
|
114
102
|
api_shares_admin.create("#{entities_path}/import", entity_parameters)[:data]
|
115
103
|
end
|
116
104
|
when :add
|
117
|
-
|
118
|
-
return do_bulk_operation(parameters, 'created') do |entity_name|
|
105
|
+
return do_bulk_operation(value_create_modify(type: :bulk_hash), 'created') do |entity_name|
|
119
106
|
raise "expecting string (name), have #{entity_name.class}" unless entity_name.is_a?(String)
|
120
107
|
api_shares_admin.create(entities_path, {entity_type=>entity_name})[:data]
|
121
108
|
end
|
109
|
+
when *USR_GRP_SETTINGS
|
110
|
+
group_id = instance_identifier
|
111
|
+
entities_path = "#{entities_path}/#{group_id}/#{entity_verb}"
|
112
|
+
return entity_action(api_shares_admin, entities_path, is_singleton: !entity_verb.eql?(:share_permissions))
|
122
113
|
end
|
123
114
|
when :share
|
124
115
|
share_command = options.get_next_command(%i[user_permissions group_permissions].concat(Plugin::ALL_OPS))
|
@@ -11,14 +11,14 @@ module Aspera
|
|
11
11
|
module Plugins
|
12
12
|
# Execute Aspera Sync
|
13
13
|
class Sync < Aspera::Cli::Plugin
|
14
|
-
def initialize(env,
|
14
|
+
def initialize(env, sync_spec: nil)
|
15
15
|
super(env)
|
16
|
-
options.
|
17
|
-
options.
|
16
|
+
options.declare(:sync_info, 'Information for sync instance and sessions', types: Hash)
|
17
|
+
options.declare(:sync_session, 'Name of session to use for admin commands. default: first in parameters')
|
18
18
|
options.parse_options!
|
19
19
|
return if env[:man_only]
|
20
|
-
@params = options.get_option(:sync_info,
|
21
|
-
|
20
|
+
@params = options.get_option(:sync_info, mandatory: true)
|
21
|
+
@sync_spec = sync_spec
|
22
22
|
end
|
23
23
|
|
24
24
|
ACTIONS = %i[start admin].freeze
|
@@ -27,7 +27,7 @@ module Aspera
|
|
27
27
|
command = options.get_next_command(ACTIONS)
|
28
28
|
case command
|
29
29
|
when :start
|
30
|
-
Aspera::Sync.new(@params).start
|
30
|
+
Aspera::Sync.new(@params, @sync_spec).start
|
31
31
|
return Main.result_success
|
32
32
|
when :admin
|
33
33
|
sync_admin = Aspera::SyncAdmin.new(@params, options.get_option(:sync_session))
|