aspera-cli 4.14.0 → 4.16.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/BUGS.md +29 -3
- data/CHANGELOG.md +300 -185
- data/CONTRIBUTING.md +74 -23
- data/README.md +2346 -1619
- data/bin/ascli +16 -25
- data/bin/asession +15 -15
- data/examples/dascli +2 -2
- data/examples/proxy.pac +1 -1
- data/lib/aspera/aoc.rb +216 -150
- data/lib/aspera/ascmd.rb +25 -18
- data/lib/aspera/assert.rb +45 -0
- data/lib/aspera/cli/basic_auth_plugin.rb +9 -6
- data/lib/aspera/cli/error.rb +17 -0
- data/lib/aspera/cli/extended_value.rb +51 -16
- data/lib/aspera/cli/formatter.rb +276 -174
- data/lib/aspera/cli/hints.rb +81 -0
- data/lib/aspera/cli/main.rb +114 -147
- data/lib/aspera/cli/manager.rb +181 -136
- data/lib/aspera/cli/plugin.rb +82 -64
- data/lib/aspera/cli/plugins/alee.rb +0 -1
- data/lib/aspera/cli/plugins/aoc.rb +327 -331
- data/lib/aspera/cli/plugins/ats.rb +12 -8
- data/lib/aspera/cli/plugins/bss.rb +2 -2
- data/lib/aspera/cli/plugins/config.rb +575 -439
- data/lib/aspera/cli/plugins/console.rb +40 -0
- data/lib/aspera/cli/plugins/cos.rb +4 -5
- data/lib/aspera/cli/plugins/faspex.rb +111 -92
- data/lib/aspera/cli/plugins/faspex5.rb +245 -182
- data/lib/aspera/cli/plugins/node.rb +239 -160
- data/lib/aspera/cli/plugins/orchestrator.rb +56 -19
- data/lib/aspera/cli/plugins/preview.rb +54 -38
- data/lib/aspera/cli/plugins/server.rb +63 -20
- data/lib/aspera/cli/plugins/shares.rb +64 -38
- data/lib/aspera/cli/sync_actions.rb +68 -0
- data/lib/aspera/cli/transfer_agent.rb +64 -67
- data/lib/aspera/cli/transfer_progress.rb +73 -0
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +3 -1
- data/lib/aspera/command_line_builder.rb +27 -22
- data/lib/aspera/cos_node.rb +6 -4
- data/lib/aspera/coverage.rb +22 -0
- data/lib/aspera/data_repository.rb +33 -2
- data/lib/aspera/environment.rb +21 -8
- data/lib/aspera/fasp/agent_alpha.rb +116 -0
- data/lib/aspera/fasp/agent_base.rb +40 -76
- data/lib/aspera/fasp/agent_connect.rb +21 -22
- data/lib/aspera/fasp/agent_direct.rb +169 -179
- data/lib/aspera/fasp/agent_httpgw.rb +200 -195
- data/lib/aspera/fasp/agent_node.rb +43 -35
- data/lib/aspera/fasp/agent_trsdk.rb +124 -41
- data/lib/aspera/fasp/error_info.rb +2 -2
- data/lib/aspera/fasp/faux_file.rb +52 -0
- data/lib/aspera/fasp/installation.rb +89 -191
- data/lib/aspera/fasp/management.rb +249 -0
- data/lib/aspera/fasp/parameters.rb +86 -47
- data/lib/aspera/fasp/parameters.yaml +75 -8
- data/lib/aspera/fasp/products.rb +162 -0
- data/lib/aspera/fasp/resume_policy.rb +7 -5
- data/lib/aspera/fasp/sync.rb +273 -0
- data/lib/aspera/fasp/transfer_spec.rb +10 -8
- data/lib/aspera/fasp/uri.rb +6 -6
- data/lib/aspera/faspex_gw.rb +11 -8
- data/lib/aspera/faspex_postproc.rb +8 -7
- data/lib/aspera/hash_ext.rb +2 -2
- data/lib/aspera/id_generator.rb +3 -1
- data/lib/aspera/json_rpc.rb +51 -0
- data/lib/aspera/keychain/encrypted_hash.rb +46 -11
- data/lib/aspera/keychain/macos_security.rb +15 -13
- data/lib/aspera/line_logger.rb +23 -0
- data/lib/aspera/log.rb +61 -19
- data/lib/aspera/nagios.rb +7 -2
- data/lib/aspera/node.rb +105 -21
- data/lib/aspera/node_simulator.rb +214 -0
- data/lib/aspera/oauth.rb +57 -36
- data/lib/aspera/open_application.rb +4 -4
- data/lib/aspera/persistency_action_once.rb +13 -14
- data/lib/aspera/persistency_folder.rb +5 -4
- data/lib/aspera/preview/file_types.rb +56 -268
- data/lib/aspera/preview/generator.rb +28 -39
- data/lib/aspera/preview/options.rb +2 -0
- data/lib/aspera/preview/terminal.rb +36 -16
- data/lib/aspera/preview/utils.rb +23 -29
- data/lib/aspera/proxy_auto_config.rb +6 -3
- data/lib/aspera/rest.rb +127 -80
- data/lib/aspera/rest_call_error.rb +1 -1
- data/lib/aspera/rest_error_analyzer.rb +16 -14
- data/lib/aspera/rest_errors_aspera.rb +39 -34
- data/lib/aspera/secret_hider.rb +18 -17
- data/lib/aspera/ssh.rb +10 -5
- data/lib/aspera/temp_file_manager.rb +11 -4
- data/lib/aspera/web_auth.rb +10 -7
- data/lib/aspera/web_server_simple.rb +11 -5
- data.tar.gz.sig +0 -0
- metadata +108 -39
- metadata.gz.sig +0 -0
- 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/fasp/listener.rb +0 -13
- data/lib/aspera/sync.rb +0 -213
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'aspera/fasp/listener'
|
|
4
|
-
require 'aspera/log'
|
|
5
|
-
|
|
6
|
-
module Aspera
|
|
7
|
-
module Cli
|
|
8
|
-
module Listener
|
|
9
|
-
# listener for FASP transfers (debug)
|
|
10
|
-
class Logger < Aspera::Fasp::Listener
|
|
11
|
-
def event_struct(data)
|
|
12
|
-
Log.log.debug(data.to_s)
|
|
13
|
-
Log.log.error((data['Description']).to_s) if data['Type'].eql?('FILEERROR')
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def event_enhanced(data)
|
|
17
|
-
Log.log.debug(JSON.generate(data))
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'aspera/fasp/listener'
|
|
4
|
-
require 'aspera/environment'
|
|
5
|
-
require 'ruby-progressbar'
|
|
6
|
-
|
|
7
|
-
module Aspera
|
|
8
|
-
module Cli
|
|
9
|
-
module Listener
|
|
10
|
-
# a listener to FASP event that displays a progress bar
|
|
11
|
-
class Progress < Aspera::Fasp::Listener
|
|
12
|
-
def initialize
|
|
13
|
-
super
|
|
14
|
-
@progress = nil
|
|
15
|
-
@cumulative = 0
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def event_struct(data)
|
|
19
|
-
case data['Type']
|
|
20
|
-
when 'NOTIFICATION'
|
|
21
|
-
if data.key?('PreTransferBytes')
|
|
22
|
-
@progress = ProgressBar.create(
|
|
23
|
-
format: '%a %B %p%% %r Mbps %e',
|
|
24
|
-
rate_scale: lambda{|rate|rate / Environment::BYTES_PER_MEBIBIT},
|
|
25
|
-
title: 'progress',
|
|
26
|
-
total: data['PreTransferBytes'].to_i)
|
|
27
|
-
end
|
|
28
|
-
when 'STOP'
|
|
29
|
-
# stop event when one file is completed
|
|
30
|
-
@cumulative += data['Size'].to_i
|
|
31
|
-
when 'STATS'
|
|
32
|
-
if @progress.nil?
|
|
33
|
-
puts '.'
|
|
34
|
-
else
|
|
35
|
-
@progress.progress = data.key?('Bytescont') ? @cumulative + data['Bytescont'].to_i : data['TransferBytes'].to_i
|
|
36
|
-
end
|
|
37
|
-
when 'DONE'
|
|
38
|
-
if @progress.nil?
|
|
39
|
-
# terminate progress by going to next line
|
|
40
|
-
puts "\n"
|
|
41
|
-
else
|
|
42
|
-
@progress.progress = @progress.total
|
|
43
|
-
@progress = nil
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'aspera/fasp/listener'
|
|
4
|
-
require 'aspera/fasp/agent_base'
|
|
5
|
-
require 'aspera/environment'
|
|
6
|
-
require 'ruby-progressbar'
|
|
7
|
-
|
|
8
|
-
module Aspera
|
|
9
|
-
module Cli
|
|
10
|
-
module Listener
|
|
11
|
-
# a listener to FASP event that displays a progress bar
|
|
12
|
-
class ProgressMulti < Aspera::Fasp::Listener
|
|
13
|
-
def initialize
|
|
14
|
-
super
|
|
15
|
-
@progress_bar = nil
|
|
16
|
-
@sessions = {}
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def reset
|
|
20
|
-
@progress_bar = nil
|
|
21
|
-
@sessions = {}
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def update_total
|
|
25
|
-
@progress_bar.total = @sessions.values.inject(0){|m, s|m + s[:job_size].to_i}
|
|
26
|
-
rescue StandardError
|
|
27
|
-
nil
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def update_progress
|
|
31
|
-
@progress_bar.progress = @sessions.values.inject(0){|m, s|m + s[:current].to_i}
|
|
32
|
-
rescue StandardError
|
|
33
|
-
nil
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def event_enhanced(data)
|
|
37
|
-
if @progress_bar.nil?
|
|
38
|
-
@progress_bar = ProgressBar.create(
|
|
39
|
-
format: '%t %a %B %p%% %r Mbps %e',
|
|
40
|
-
rate_scale: lambda{|rate|rate / Environment::BYTES_PER_MEBIBIT},
|
|
41
|
-
title: '',
|
|
42
|
-
total: nil)
|
|
43
|
-
end
|
|
44
|
-
if !data.key?(Fasp::AgentBase::LISTENER_SESSION_ID_S)
|
|
45
|
-
Log.log.error{"Internal error: no #{Fasp::AgentBase::LISTENER_SESSION_ID_S} in event: #{data}"}
|
|
46
|
-
return
|
|
47
|
-
end
|
|
48
|
-
new_title = @sessions.length < 2 ? '' : "multi=#{@sessions.length}"
|
|
49
|
-
@progress_bar.title = new_title unless @progress_bar.title.eql?(new_title)
|
|
50
|
-
session = @sessions[data[Fasp::AgentBase::LISTENER_SESSION_ID_S]] ||= {
|
|
51
|
-
cumulative: 0,
|
|
52
|
-
job_size: 0,
|
|
53
|
-
current: 0
|
|
54
|
-
}
|
|
55
|
-
case data['type']
|
|
56
|
-
when 'INIT' # connection to ascp (get id)
|
|
57
|
-
when 'SESSION' # session information
|
|
58
|
-
when 'NOTIFICATION' # sent from remote
|
|
59
|
-
if data.key?('pre_transfer_bytes')
|
|
60
|
-
session[:job_size] = data['pre_transfer_bytes']
|
|
61
|
-
update_total
|
|
62
|
-
end
|
|
63
|
-
when 'STATS' # during transfer
|
|
64
|
-
if @progress_bar.total.nil?
|
|
65
|
-
@progress_bar.increment
|
|
66
|
-
else
|
|
67
|
-
session[:current] = data.key?('bytescont') ? session[:cumulative] + data['bytescont'].to_i : data['transfer_bytes'].to_i
|
|
68
|
-
update_progress
|
|
69
|
-
end
|
|
70
|
-
when 'STOP'
|
|
71
|
-
# stop event when one file is completed
|
|
72
|
-
session[:cumulative] = session[:cumulative] + data['size'].to_i
|
|
73
|
-
when 'DONE' # end of session
|
|
74
|
-
@sessions.delete(data[Fasp::AgentBase::LISTENER_SESSION_ID_S])
|
|
75
|
-
update_progress
|
|
76
|
-
update_total
|
|
77
|
-
else
|
|
78
|
-
Log.log.debug{"ignore: #{data['type']}"}
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'English'
|
|
4
|
-
require 'aspera/cli/plugin'
|
|
5
|
-
require 'aspera/sync'
|
|
6
|
-
require 'aspera/log'
|
|
7
|
-
require 'open3'
|
|
8
|
-
|
|
9
|
-
module Aspera
|
|
10
|
-
module Cli
|
|
11
|
-
module Plugins
|
|
12
|
-
# Execute Aspera Sync
|
|
13
|
-
class Sync < Aspera::Cli::Plugin
|
|
14
|
-
def initialize(env, sync_spec: nil)
|
|
15
|
-
super(env)
|
|
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
|
-
options.parse_options!
|
|
19
|
-
return if env[:man_only]
|
|
20
|
-
@params = options.get_option(:sync_info, mandatory: true)
|
|
21
|
-
@sync_spec = sync_spec
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
ACTIONS = %i[start admin].freeze
|
|
25
|
-
|
|
26
|
-
def execute_action
|
|
27
|
-
command = options.get_next_command(ACTIONS)
|
|
28
|
-
case command
|
|
29
|
-
when :start
|
|
30
|
-
Aspera::Sync.new(@params, @sync_spec).start
|
|
31
|
-
return Main.result_success
|
|
32
|
-
when :admin
|
|
33
|
-
sync_admin = Aspera::SyncAdmin.new(@params, options.get_option(:sync_session))
|
|
34
|
-
command2 = options.get_next_command([:status])
|
|
35
|
-
case command2
|
|
36
|
-
when :status
|
|
37
|
-
return {type: :single_object, data: sync_admin.status}
|
|
38
|
-
end # command2
|
|
39
|
-
end # command
|
|
40
|
-
end # execute_action
|
|
41
|
-
end # Sync
|
|
42
|
-
end # Plugins
|
|
43
|
-
end # Cli
|
|
44
|
-
end # Aspera
|
data/lib/aspera/fasp/listener.rb
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Aspera
|
|
4
|
-
module Fasp
|
|
5
|
-
# implement this class to get transfer events
|
|
6
|
-
class Listener # rubocop:disable Lint/EmptyClass
|
|
7
|
-
# define one of the following methods:
|
|
8
|
-
# event_text(text_data)
|
|
9
|
-
# event_struct(legacy_names)
|
|
10
|
-
# event_enhanced(snake_names)
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
data/lib/aspera/sync.rb
DELETED
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# cspell:words logdir
|
|
4
|
-
|
|
5
|
-
require 'aspera/command_line_builder'
|
|
6
|
-
require 'aspera/fasp/installation'
|
|
7
|
-
require 'json'
|
|
8
|
-
require 'base64'
|
|
9
|
-
|
|
10
|
-
module Aspera
|
|
11
|
-
# builds command line arg for async
|
|
12
|
-
class Sync
|
|
13
|
-
# default is push
|
|
14
|
-
DIRECTIONS = %i[push pull bidi].freeze
|
|
15
|
-
DIRECTION_TO_REQUEST_TYPE = {
|
|
16
|
-
push: :sync_upload,
|
|
17
|
-
pull: :sync_download,
|
|
18
|
-
bidi: :sync
|
|
19
|
-
}.freeze
|
|
20
|
-
PARAMS_VX_INSTANCE =
|
|
21
|
-
{
|
|
22
|
-
'alt_logdir' => { cli: { type: :opt_with_arg}, accepted_types: :string},
|
|
23
|
-
'watchd' => { cli: { type: :opt_with_arg}, accepted_types: :string},
|
|
24
|
-
'apply_local_docroot' => { cli: { type: :opt_without_arg}},
|
|
25
|
-
'quiet' => { cli: { type: :opt_without_arg}},
|
|
26
|
-
'ws_connect' => { cli: { type: :opt_without_arg}}
|
|
27
|
-
}.freeze
|
|
28
|
-
|
|
29
|
-
# map sync session parameters to transfer spec: sync -> ts, true if same
|
|
30
|
-
PARAMS_VX_SESSION =
|
|
31
|
-
{
|
|
32
|
-
'name' => { cli: { type: :opt_with_arg}, accepted_types: :string},
|
|
33
|
-
'local_dir' => { cli: { type: :opt_with_arg}, accepted_types: :string},
|
|
34
|
-
'remote_dir' => { cli: { type: :opt_with_arg}, accepted_types: :string},
|
|
35
|
-
'local_db_dir' => { cli: { type: :opt_with_arg}, accepted_types: :string},
|
|
36
|
-
'remote_db_dir' => { cli: { type: :opt_with_arg}, accepted_types: :string},
|
|
37
|
-
'host' => { cli: { type: :opt_with_arg}, accepted_types: :string, ts: :remote_host},
|
|
38
|
-
'user' => { cli: { type: :opt_with_arg}, accepted_types: :string, ts: :remote_user},
|
|
39
|
-
'private_key_paths' => { cli: { type: :opt_with_arg, switch: '--private-key-path'}, accepted_types: :array},
|
|
40
|
-
'direction' => { cli: { type: :opt_with_arg}, accepted_types: :string},
|
|
41
|
-
'checksum' => { cli: { type: :opt_with_arg}, accepted_types: :string},
|
|
42
|
-
'tags' => { cli: { type: :opt_with_arg, switch: '--tags64', convert: 'Aspera::Fasp::Parameters.convert_json64'},
|
|
43
|
-
accepted_types: :hash, ts: true},
|
|
44
|
-
'tcp_port' => { cli: { type: :opt_with_arg}, accepted_types: :int, ts: :ssh_port},
|
|
45
|
-
'rate_policy' => { cli: { type: :opt_with_arg}, accepted_types: :string},
|
|
46
|
-
'target_rate' => { cli: { type: :opt_with_arg}, accepted_types: :string},
|
|
47
|
-
'cooloff' => { cli: { type: :opt_with_arg}, accepted_types: :int},
|
|
48
|
-
'pending_max' => { cli: { type: :opt_with_arg}, accepted_types: :int},
|
|
49
|
-
'scan_intensity' => { cli: { type: :opt_with_arg}, accepted_types: :string},
|
|
50
|
-
'cipher' => { cli: { type: :opt_with_arg, convert: 'Aspera::Fasp::Parameters.convert_remove_hyphen'}, accepted_types: :string, ts: true},
|
|
51
|
-
'transfer_threads' => { cli: { type: :opt_with_arg}, accepted_types: :int},
|
|
52
|
-
'preserve_time' => { cli: { type: :opt_without_arg}, ts: :preserve_times},
|
|
53
|
-
'preserve_access_time' => { cli: { type: :opt_without_arg}, ts: nil},
|
|
54
|
-
'preserve_modification_time' => { cli: { type: :opt_without_arg}, ts: nil},
|
|
55
|
-
'preserve_uid' => { cli: { type: :opt_without_arg}, ts: :preserve_file_owner_uid},
|
|
56
|
-
'preserve_gid' => { cli: { type: :opt_without_arg}, ts: :preserve_file_owner_gid},
|
|
57
|
-
'create_dir' => { cli: { type: :opt_without_arg}, ts: true},
|
|
58
|
-
'reset' => { cli: { type: :opt_without_arg}},
|
|
59
|
-
# NOTE: only one env var, but multiple sessions... could be a problem
|
|
60
|
-
'remote_password' => { cli: { type: :envvar, variable: 'ASPERA_SCP_PASS'}, ts: true},
|
|
61
|
-
'cookie' => { cli: { type: :envvar, variable: 'ASPERA_SCP_COOKIE'}, ts: true},
|
|
62
|
-
'token' => { cli: { type: :envvar, variable: 'ASPERA_SCP_TOKEN'}, ts: true},
|
|
63
|
-
'license' => { cli: { type: :envvar, variable: 'ASPERA_SCP_LICENSE'}}
|
|
64
|
-
}.freeze
|
|
65
|
-
|
|
66
|
-
Aspera::CommandLineBuilder.normalize_description(PARAMS_VX_INSTANCE)
|
|
67
|
-
Aspera::CommandLineBuilder.normalize_description(PARAMS_VX_SESSION)
|
|
68
|
-
|
|
69
|
-
PARAMS_VX_KEYS = %w[instance sessions].freeze
|
|
70
|
-
|
|
71
|
-
# new API
|
|
72
|
-
TS_TO_PARAMS_V2 = {
|
|
73
|
-
'remote_host' => 'remote.host',
|
|
74
|
-
'remote_user' => 'remote.user',
|
|
75
|
-
'remote_password' => 'remote.pass',
|
|
76
|
-
'sshfp' => 'remote.fingerprint',
|
|
77
|
-
'ssh_port' => 'remote.port',
|
|
78
|
-
'wss_port' => 'remote.ws_port',
|
|
79
|
-
'proxy' => 'remote.proxy',
|
|
80
|
-
'token' => 'remote.token',
|
|
81
|
-
'tags' => 'tags'
|
|
82
|
-
}.freeze
|
|
83
|
-
|
|
84
|
-
ASYNC_EXECUTABLE = 'async'
|
|
85
|
-
|
|
86
|
-
private_constant :PARAMS_VX_INSTANCE, :PARAMS_VX_SESSION, :PARAMS_VX_KEYS, :ASYNC_EXECUTABLE, :TS_TO_PARAMS_V2
|
|
87
|
-
|
|
88
|
-
attr_reader :env_args
|
|
89
|
-
|
|
90
|
-
# @param sync_params [Hash] sync parameters, old or new format
|
|
91
|
-
# @param node_sync [Object|nil]
|
|
92
|
-
def initialize(sync_params, node_sync)
|
|
93
|
-
raise StandardError, 'parameter must be Hash' unless sync_params.is_a?(Hash)
|
|
94
|
-
raise 'node_sync misses method transfer_spec' unless node_sync.nil? || node_sync.respond_to?(:transfer_spec)
|
|
95
|
-
@env_args = {
|
|
96
|
-
args: [],
|
|
97
|
-
env: {}
|
|
98
|
-
}
|
|
99
|
-
if sync_params.key?('local')
|
|
100
|
-
# async native JSON format (v2)
|
|
101
|
-
raise StandardError, 'remote must be Hash' unless sync_params['remote'].is_a?(Hash)
|
|
102
|
-
unless node_sync.nil?
|
|
103
|
-
transfer_spec = node_sync.transfer_spec(sync_params['direction'], sync_params['local']['path'], sync_params['remote']['path'])
|
|
104
|
-
# async native JSON format
|
|
105
|
-
raise StandardError, 'local must be Hash' unless sync_params['local'].is_a?(Hash)
|
|
106
|
-
TS_TO_PARAMS_V2.each do |ts_param, sy_path|
|
|
107
|
-
next unless transfer_spec.key?(ts_param)
|
|
108
|
-
sy_dig = sy_path.split('.')
|
|
109
|
-
param = sy_dig.pop
|
|
110
|
-
hash = sy_dig.empty? ? sync_params : sync_params[sy_dig.first]
|
|
111
|
-
hash = sync_params[sy_dig.first] = {} if hash.nil?
|
|
112
|
-
hash[param] = transfer_spec[ts_param]
|
|
113
|
-
end
|
|
114
|
-
# 'remote.path',
|
|
115
|
-
sync_params['remote']['connect_mode'] ||= sync_params['remote'].key?('ws_port') ? 'ws' : 'ssh'
|
|
116
|
-
sync_params['remote']['private_key_paths'] ||= Fasp::Installation.instance.bypass_keys if transfer_spec.key?('token')
|
|
117
|
-
sync_params['remote']['path'] ||= '/' if transfer_spec.dig(*%w[tags aspera node file_id])
|
|
118
|
-
end
|
|
119
|
-
@env_args[:args] = ["--conf64=#{Base64.strict_encode64(JSON.generate(sync_params))}"]
|
|
120
|
-
elsif sync_params.key?('sessions')
|
|
121
|
-
# ascli JSON format (v1)
|
|
122
|
-
unless node_sync.nil?
|
|
123
|
-
sync_params['sessions'].each do |session|
|
|
124
|
-
transfer_spec = node_sync.transfer_spec(session['direction'], session['local_dir'], session['remote_dir'])
|
|
125
|
-
PARAMS_VX_SESSION.each do |async_param, behavior|
|
|
126
|
-
if behavior.key?(:ts)
|
|
127
|
-
tspec_param = behavior[:ts].is_a?(TrueClass) ? async_param : behavior[:ts].to_s
|
|
128
|
-
session[async_param] ||= transfer_spec[tspec_param] if transfer_spec.key?(tspec_param)
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
session['private_key_paths'] = Fasp::Installation.instance.bypass_keys if transfer_spec.key?('token')
|
|
132
|
-
session['remote_dir'] = '/' if transfer_spec.dig(*%w[tags aspera node file_id])
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
raise StandardError, "Only 'sessions', and optionally 'instance' keys are allowed" unless
|
|
136
|
-
sync_params.keys.push('instance').uniq.sort.eql?(PARAMS_VX_KEYS)
|
|
137
|
-
raise StandardError, 'sessions key must be Array' unless sync_params['sessions'].is_a?(Array)
|
|
138
|
-
raise StandardError, 'sessions key requires at least one Hash' unless sync_params['sessions'].first.is_a?(Hash)
|
|
139
|
-
|
|
140
|
-
if sync_params.key?('instance')
|
|
141
|
-
raise StandardError, 'instance key must be Hash' unless sync_params['instance'].is_a?(Hash)
|
|
142
|
-
instance_builder = Aspera::CommandLineBuilder.new(sync_params['instance'], PARAMS_VX_INSTANCE)
|
|
143
|
-
instance_builder.process_params
|
|
144
|
-
instance_builder.add_env_args(@env_args[:env], @env_args[:args])
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
sync_params['sessions'].each do |session_params|
|
|
148
|
-
raise StandardError, 'sessions must contain hashes' unless session_params.is_a?(Hash)
|
|
149
|
-
raise StandardError, 'session must contain at least name' unless session_params.key?('name')
|
|
150
|
-
session_builder = Aspera::CommandLineBuilder.new(session_params, PARAMS_VX_SESSION)
|
|
151
|
-
session_builder.process_params
|
|
152
|
-
session_builder.add_env_args(@env_args[:env], @env_args[:args])
|
|
153
|
-
end
|
|
154
|
-
else
|
|
155
|
-
raise 'At least one of `local` or `sessions` must be present in async parameters'
|
|
156
|
-
end
|
|
157
|
-
Log.dump(:sync, sync_params)
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
def start
|
|
161
|
-
Log.log.debug{"execute: #{@env_args[:env].map{|k, v| "#{k}=\"#{v}\""}.join(' ')} \"#{ASYNC_EXECUTABLE}\" \"#{@env_args[:args].join('" "')}\""}
|
|
162
|
-
res = system(@env_args[:env], [ASYNC_EXECUTABLE, ASYNC_EXECUTABLE], *@env_args[:args])
|
|
163
|
-
Log.log.debug{"result=#{res}"}
|
|
164
|
-
case res
|
|
165
|
-
when true then return nil
|
|
166
|
-
when false then raise "failed: #{$CHILD_STATUS}"
|
|
167
|
-
when nil then raise "not started: #{$CHILD_STATUS}"
|
|
168
|
-
else raise 'internal error: unspecified case'
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
end # end Sync
|
|
172
|
-
|
|
173
|
-
class SyncAdmin
|
|
174
|
-
ASYNC_ADMIN_EXECUTABLE = 'asyncadmin'
|
|
175
|
-
private_constant :ASYNC_ADMIN_EXECUTABLE
|
|
176
|
-
def initialize(sync_params, session_name)
|
|
177
|
-
@cmdline = [ASYNC_ADMIN_EXECUTABLE, '--quiet']
|
|
178
|
-
if sync_params.key?('local')
|
|
179
|
-
raise 'Missing session name' if sync_params['name'].nil?
|
|
180
|
-
raise 'Session not found' unless session_name.nil? || session_name.eql?(sync_params['name'])
|
|
181
|
-
@cmdline.push("--name=#{sync_params['name']}")
|
|
182
|
-
if sync_params.key?('local_db_dir')
|
|
183
|
-
@cmdline.push("--local-db-dir=#{sync_params['local_db_dir']}")
|
|
184
|
-
elsif sync_params.dig('local', 'path')
|
|
185
|
-
@cmdline.push("--local-dir=#{sync_params.dig('local', 'path')}")
|
|
186
|
-
else
|
|
187
|
-
raise 'Missing either local_db_dir or local.path'
|
|
188
|
-
end
|
|
189
|
-
elsif sync_params.key?('sessions')
|
|
190
|
-
session = session_name.nil? ? sync_params['sessions'].first : sync_params['sessions'].find{|s|s['name'].eql?(session_name)}
|
|
191
|
-
raise 'Session not found' if session.nil?
|
|
192
|
-
raise 'Missing session name' if session['name'].nil?
|
|
193
|
-
@cmdline.push("--name=#{session['name']}")
|
|
194
|
-
if session.key?('local_db_dir')
|
|
195
|
-
@cmdline.push("--local-db-dir=#{session['local_db_dir']}")
|
|
196
|
-
elsif session.key?('local_dir')
|
|
197
|
-
@cmdline.push("--local-dir=#{session['local_dir']}")
|
|
198
|
-
else
|
|
199
|
-
raise 'Missing either local_db_dir or local_dir'
|
|
200
|
-
end
|
|
201
|
-
else
|
|
202
|
-
raise 'At least one of `local` or `sessions` must be present in async parameters'
|
|
203
|
-
end
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
def status
|
|
207
|
-
stdout, stderr, status = Open3.capture3(*@cmdline)
|
|
208
|
-
Log.log.debug{"status=#{status}, stderr=#{stderr}"}
|
|
209
|
-
raise "Sync failed: #{status.exitstatus} : #{stderr}" unless status.success?
|
|
210
|
-
return stdout.split("\n").each_with_object({}){|l, m|i = l.split(/: */); m[i.first.lstrip] = i.last.lstrip} # rubocop:disable Style/Semicolon
|
|
211
|
-
end
|
|
212
|
-
end
|
|
213
|
-
end
|