aspera-cli 4.24.1 → 4.24.2
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 +15 -2
- data/README.md +745 -436
- data/bin/ascli +20 -1
- data/bin/asession +23 -27
- data/lib/aspera/agent/base.rb +10 -21
- data/lib/aspera/agent/connect.rb +2 -3
- data/lib/aspera/agent/desktop.rb +2 -2
- data/lib/aspera/agent/direct.rb +49 -32
- data/lib/aspera/agent/factory.rb +31 -0
- data/lib/aspera/api/aoc.rb +79 -49
- data/lib/aspera/api/faspex.rb +212 -0
- data/lib/aspera/api/node.rb +99 -84
- data/lib/aspera/ascp/installation.rb +22 -21
- data/lib/aspera/ascp/management.rb +119 -23
- data/lib/aspera/assert.rb +14 -8
- data/lib/aspera/cli/extended_value.rb +15 -15
- data/lib/aspera/cli/formatter.rb +7 -5
- data/lib/aspera/cli/hints.rb +8 -0
- data/lib/aspera/cli/info.rb +4 -4
- data/lib/aspera/cli/main.rb +55 -70
- data/lib/aspera/cli/manager.rb +7 -4
- data/lib/aspera/cli/plugins/alee.rb +2 -1
- data/lib/aspera/cli/plugins/aoc.rb +110 -186
- data/lib/aspera/cli/plugins/ats.rb +4 -4
- data/lib/aspera/cli/plugins/base.rb +335 -0
- data/lib/aspera/cli/plugins/basic_auth.rb +45 -0
- data/lib/aspera/cli/plugins/config.rb +249 -220
- data/lib/aspera/cli/plugins/console.rb +15 -15
- data/lib/aspera/cli/plugins/cos.rb +2 -2
- data/lib/aspera/cli/plugins/factory.rb +78 -0
- data/lib/aspera/cli/plugins/faspex.rb +17 -20
- data/lib/aspera/cli/plugins/faspex5.rb +79 -193
- data/lib/aspera/cli/plugins/faspio.rb +14 -13
- data/lib/aspera/cli/plugins/httpgw.rb +13 -12
- data/lib/aspera/cli/plugins/node.rb +34 -32
- data/lib/aspera/cli/plugins/oauth.rb +48 -0
- data/lib/aspera/cli/plugins/orchestrator.rb +15 -13
- data/lib/aspera/cli/plugins/preview.rb +4 -4
- data/lib/aspera/cli/plugins/server.rb +15 -13
- data/lib/aspera/cli/plugins/shares.rb +18 -15
- data/lib/aspera/cli/sync_actions.rb +1 -1
- data/lib/aspera/cli/transfer_agent.rb +24 -20
- data/lib/aspera/cli/transfer_progress.rb +6 -6
- data/lib/aspera/cli/version.rb +3 -3
- data/lib/aspera/cli/wizard.rb +65 -53
- data/lib/aspera/colors.rb +6 -0
- data/lib/aspera/command_line_builder.rb +45 -50
- data/lib/aspera/command_line_converter.rb +2 -1
- data/lib/aspera/coverage.rb +1 -1
- data/lib/aspera/data_repository.rb +1 -1
- data/lib/aspera/environment.rb +10 -7
- data/lib/aspera/faspex_gw.rb +6 -4
- data/lib/aspera/faspex_postproc.rb +1 -1
- data/lib/aspera/keychain/macos_security.rb +1 -1
- data/lib/aspera/log.rb +37 -9
- data/lib/aspera/nagios.rb +1 -1
- data/lib/aspera/oauth/base.rb +17 -10
- data/lib/aspera/oauth/factory.rb +8 -8
- data/lib/aspera/oauth/web.rb +2 -2
- data/lib/aspera/products/connect.rb +4 -3
- data/lib/aspera/products/desktop.rb +1 -4
- data/lib/aspera/products/other.rb +9 -1
- data/lib/aspera/products/transferd.rb +0 -1
- data/lib/aspera/rest.rb +126 -83
- data/lib/aspera/ssh.rb +3 -3
- data/lib/aspera/sync/args.schema.yaml +46 -3
- data/lib/aspera/sync/conf.schema.yaml +130 -94
- data/lib/aspera/sync/operations.rb +16 -16
- data/lib/aspera/temp_file_manager.rb +17 -5
- data/lib/aspera/transfer/error.rb +16 -7
- data/lib/aspera/transfer/parameters.rb +34 -20
- data/lib/aspera/transfer/resumer.rb +74 -0
- data/lib/aspera/transfer/spec.rb +4 -3
- data/lib/aspera/transfer/spec.schema.yaml +132 -51
- data/lib/aspera/transfer/spec_doc.rb +41 -35
- data/lib/aspera/uri_reader.rb +1 -1
- data/lib/aspera/web_auth.rb +6 -6
- data.tar.gz.sig +0 -0
- metadata +9 -7
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/basic_auth_plugin.rb +0 -43
- data/lib/aspera/cli/plugin.rb +0 -333
- data/lib/aspera/cli/plugin_factory.rb +0 -81
- data/lib/aspera/resumer.rb +0 -77
- data/lib/aspera/transfer/error_info.rb +0 -91
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# cspell:ignore snid fnid bidi ssync asyncs rund asnodeadmin mkfile mklink asperabrowser asperabrowserurl watchfolders watchfolderd entsrv
|
|
4
|
-
require 'aspera/cli/
|
|
4
|
+
require 'aspera/cli/plugins/basic_auth'
|
|
5
5
|
require 'aspera/cli/sync_actions'
|
|
6
6
|
require 'aspera/cli/special_values'
|
|
7
7
|
require 'aspera/transfer/spec'
|
|
@@ -9,7 +9,6 @@ require 'aspera/nagios'
|
|
|
9
9
|
require 'aspera/hash_ext'
|
|
10
10
|
require 'aspera/id_generator'
|
|
11
11
|
require 'aspera/api/node'
|
|
12
|
-
require 'aspera/api/aoc'
|
|
13
12
|
require 'aspera/oauth'
|
|
14
13
|
require 'aspera/node_simulator'
|
|
15
14
|
require 'aspera/assert'
|
|
@@ -19,7 +18,7 @@ require 'zlib'
|
|
|
19
18
|
module Aspera
|
|
20
19
|
module Cli
|
|
21
20
|
module Plugins
|
|
22
|
-
class Node <
|
|
21
|
+
class Node < BasicAuth
|
|
23
22
|
include SyncActions
|
|
24
23
|
|
|
25
24
|
class << self
|
|
@@ -62,18 +61,6 @@ module Aspera
|
|
|
62
61
|
return
|
|
63
62
|
end
|
|
64
63
|
|
|
65
|
-
def wizard(object:, _private_key_path: nil, _pub_key_pem: nil)
|
|
66
|
-
options = object.options
|
|
67
|
-
return {
|
|
68
|
-
preset_value: {
|
|
69
|
-
url: options.get_option(:url, mandatory: true),
|
|
70
|
-
username: options.get_option(:username, mandatory: true),
|
|
71
|
-
password: options.get_option(:password, mandatory: true)
|
|
72
|
-
},
|
|
73
|
-
test_args: 'info'
|
|
74
|
-
}
|
|
75
|
-
end
|
|
76
|
-
|
|
77
64
|
def declare_options(options)
|
|
78
65
|
return if @options_declared
|
|
79
66
|
@options_declared = true
|
|
@@ -100,6 +87,20 @@ module Aspera
|
|
|
100
87
|
end
|
|
101
88
|
end
|
|
102
89
|
|
|
90
|
+
# @param wizard [Wizard] The wizard object
|
|
91
|
+
# @param app_url [Wizard] The wizard object
|
|
92
|
+
# @return [Hash] :preset_value, :test_args
|
|
93
|
+
def wizard(wizard, app_url)
|
|
94
|
+
return {
|
|
95
|
+
preset_value: {
|
|
96
|
+
url: app_url,
|
|
97
|
+
username: options.get_option(:username, mandatory: true),
|
|
98
|
+
password: options.get_option(:password, mandatory: true)
|
|
99
|
+
},
|
|
100
|
+
test_args: 'info'
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
|
|
103
104
|
# spellchecker: disable
|
|
104
105
|
# SOAP API call to test central API
|
|
105
106
|
CENTRAL_SOAP_API_TEST = '<?xml version="1.0" encoding="UTF-8"?>' \
|
|
@@ -395,9 +396,9 @@ module Aspera
|
|
|
395
396
|
when *COMMANDS_GEN3
|
|
396
397
|
execute_command_gen3(command)
|
|
397
398
|
when :access_keys
|
|
398
|
-
ak_command = options.get_next_command(%i[do set_bearer_key].concat(
|
|
399
|
+
ak_command = options.get_next_command(%i[do set_bearer_key].concat(ALL_OPS))
|
|
399
400
|
case ak_command
|
|
400
|
-
when *
|
|
401
|
+
when *ALL_OPS
|
|
401
402
|
return entity_execute(
|
|
402
403
|
api: @api_node,
|
|
403
404
|
entity: 'access_keys',
|
|
@@ -437,7 +438,7 @@ module Aspera
|
|
|
437
438
|
nagios.add_ok('node api', 'accessible')
|
|
438
439
|
nagios.check_time_offset(info['current_time'], 'node api')
|
|
439
440
|
nagios.check_product_version('node api', 'entsrv', info['version'])
|
|
440
|
-
rescue
|
|
441
|
+
rescue RestCallError => e
|
|
441
442
|
nagios.add_critical('node api', e.to_s)
|
|
442
443
|
end
|
|
443
444
|
begin
|
|
@@ -475,7 +476,7 @@ module Aspera
|
|
|
475
476
|
# Allows to specify a file by its path or by its id on the node in command line
|
|
476
477
|
# @return [Hash] api and main file id for given path or id in next argument
|
|
477
478
|
def apifid_from_next_arg(top_file_id)
|
|
478
|
-
file_path = instance_identifier(description: 'path or %id:<id>') do |attribute, value|
|
|
479
|
+
file_path = instance_identifier(description: 'path or %id:<id> or %id:') do |attribute, value|
|
|
479
480
|
raise BadArgument, 'Only selection "id" is supported (file id)' unless attribute.eql?('id')
|
|
480
481
|
# directly return result for method
|
|
481
482
|
return {api: @api_node, file_id: value}
|
|
@@ -517,12 +518,12 @@ module Aspera
|
|
|
517
518
|
return Main.result_text(result[:password])
|
|
518
519
|
when :browse
|
|
519
520
|
apifid = apifid_from_next_arg(top_file_id)
|
|
520
|
-
file_info = apifid[:api].
|
|
521
|
+
file_info = apifid[:api].read("files/#{apifid[:file_id]}", **Api::Node.cache_control)
|
|
521
522
|
unless file_info['type'].eql?('folder')
|
|
522
523
|
# a single file
|
|
523
524
|
return Main.result_object_list([file_info], fields: GEN4_LS_FIELDS)
|
|
524
525
|
end
|
|
525
|
-
return Main.result_object_list(apifid[:api].list_files(apifid[:file_id]), fields: GEN4_LS_FIELDS)
|
|
526
|
+
return Main.result_object_list(apifid[:api].list_files(apifid[:file_id], query: query_read_delete), fields: GEN4_LS_FIELDS)
|
|
526
527
|
when :find
|
|
527
528
|
apifid = apifid_from_next_arg(top_file_id)
|
|
528
529
|
find_lambda = Api::Node.file_matcher_from_argument(options)
|
|
@@ -628,7 +629,7 @@ module Aspera
|
|
|
628
629
|
command_perm = options.get_next_command(%i[list show create delete])
|
|
629
630
|
case command_perm
|
|
630
631
|
when :list
|
|
631
|
-
list_query = query_read_delete(default: {'include' =>
|
|
632
|
+
list_query = query_read_delete(default: Rest.php_style({'include' => %w[access_level permission_count]}))
|
|
632
633
|
# specify file to get permissions for unless not specified
|
|
633
634
|
list_query['file_id'] = apifid[:file_id] unless apifid[:file_id].to_s.empty?
|
|
634
635
|
list_query['inherited'] = false if list_query.key?('file_id') && !list_query.key?('inherited')
|
|
@@ -820,9 +821,9 @@ module Aspera
|
|
|
820
821
|
when :async then return execute_async # former API
|
|
821
822
|
when :ssync
|
|
822
823
|
# Node API: /asyncs (newer)
|
|
823
|
-
sync_command = options.get_next_command(%i[start stop bandwidth counters files state summary] +
|
|
824
|
+
sync_command = options.get_next_command(%i[start stop bandwidth counters files state summary] + ALL_OPS - %i[modify])
|
|
824
825
|
case sync_command
|
|
825
|
-
when *
|
|
826
|
+
when *ALL_OPS
|
|
826
827
|
return entity_execute(
|
|
827
828
|
api: @api_node,
|
|
828
829
|
entity: :asyncs,
|
|
@@ -893,21 +894,22 @@ module Aspera
|
|
|
893
894
|
return Main.result_object_list(transfers_data, fields: %w[id status start_spec.direction start_spec.remote_user start_spec.remote_host start_spec.destination_path])
|
|
894
895
|
when :sessions
|
|
895
896
|
transfers_data = @api_node.read('ops/transfers', query_read_delete)
|
|
896
|
-
sessions = transfers_data.
|
|
897
|
+
sessions = transfers_data.flat_map{ |t| t['sessions']}
|
|
897
898
|
sessions.each do |session|
|
|
898
|
-
|
|
899
|
-
|
|
899
|
+
%i[start end].each do |what|
|
|
900
|
+
session["#{what}_time"] = session["#{what}_time_usec"] ? Time.at(session["#{what}_time_usec"] / 1_000_000.0).utc.iso8601(0) : nil
|
|
901
|
+
end
|
|
900
902
|
end
|
|
901
903
|
return Main.result_object_list(sessions, fields: %w[id status start_time end_time target_rate_kbps])
|
|
902
904
|
when :cancel
|
|
903
|
-
|
|
904
|
-
return Main.
|
|
905
|
+
@api_node.cancel("ops/transfers/#{instance_identifier}")
|
|
906
|
+
return Main.result_status('Cancelled')
|
|
905
907
|
when :show
|
|
906
908
|
resp = @api_node.read("ops/transfers/#{instance_identifier}")
|
|
907
909
|
return Main.result_single_object(resp)
|
|
908
910
|
when :modify
|
|
909
|
-
|
|
910
|
-
return Main.
|
|
911
|
+
@api_node.update("ops/transfers/#{instance_identifier}", options.get_next_argument('update value', validation: Hash))
|
|
912
|
+
return Main.result_status('Modified')
|
|
911
913
|
when :bandwidth_average
|
|
912
914
|
transfers_data = @api_node.read('ops/transfers', query_read_delete)
|
|
913
915
|
# collect all key dates
|
|
@@ -1148,7 +1150,7 @@ module Aspera
|
|
|
1148
1150
|
unless link_info.nil?
|
|
1149
1151
|
m = link_info.match(/<([^>]+)>/)
|
|
1150
1152
|
Aspera.assert(m){"Cannot parse iteration in Link: #{link_info}"}
|
|
1151
|
-
next_iteration_token =
|
|
1153
|
+
next_iteration_token = Rest.query_to_h(URI.parse(m[1]).query)['iteration_token']
|
|
1152
1154
|
end
|
|
1153
1155
|
# same as last iteration: stop
|
|
1154
1156
|
break if next_iteration_token&.eql?(query_token[:iteration_token])
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'aspera/cli/plugins/basic_auth'
|
|
4
|
+
|
|
5
|
+
module Aspera
|
|
6
|
+
module Cli
|
|
7
|
+
module Plugins
|
|
8
|
+
# base class for applications supporting OAuth 2.0 authentication
|
|
9
|
+
class Oauth < BasicAuth
|
|
10
|
+
# OAuth methods supported
|
|
11
|
+
AUTH_TYPES = %i[web jwt boot].freeze
|
|
12
|
+
# Options used for authentication
|
|
13
|
+
AUTH_OPTIONS = %i[url auth client_id client_secret scope redirect_uri private_key passphrase username password].freeze
|
|
14
|
+
def initialize(**_)
|
|
15
|
+
super
|
|
16
|
+
options.declare(:auth, 'OAuth type of authentication', values: AUTH_TYPES, default: :jwt)
|
|
17
|
+
options.declare(:client_id, 'OAuth client identifier')
|
|
18
|
+
options.declare(:client_secret, 'OAuth client secret')
|
|
19
|
+
options.declare(:redirect_uri, 'OAuth (Web) redirect URI for web authentication')
|
|
20
|
+
options.declare(:private_key, 'OAuth (JWT) RSA private key PEM value (prefix file path with @file:)')
|
|
21
|
+
options.declare(:passphrase, 'OAuth (JWT) RSA private key passphrase')
|
|
22
|
+
options.declare(:scope, 'OAuth scope for API calls')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Get all options specified by AUTH_OPTIONS and add.keys
|
|
26
|
+
# Adds those not nil to the `base`.
|
|
27
|
+
# Instantiate the provided `klass` with those kwargs.
|
|
28
|
+
# `add` can specify a default value (not `nil`)
|
|
29
|
+
# @param klass [Class] API object to create
|
|
30
|
+
# @param base [Hash] The base options for creation
|
|
31
|
+
# @param add [Hash] Additional options, key=symbol, value:default value or nil
|
|
32
|
+
def new_with_options(klass, base: {}, add: {})
|
|
33
|
+
klass.new(**
|
|
34
|
+
(AUTH_OPTIONS + add.keys).each_with_object(base) do |i, m|
|
|
35
|
+
v = options.get_option(i)
|
|
36
|
+
m[i] = v unless v.nil?
|
|
37
|
+
m[i] = add[i] unless !m[i].nil? || add[i].nil?
|
|
38
|
+
end)
|
|
39
|
+
rescue ::ArgumentError => e
|
|
40
|
+
if (m = e.message.match(/missing keyword: :(.*)$/))
|
|
41
|
+
raise Cli::Error, "Missing option: #{m[1]}"
|
|
42
|
+
end
|
|
43
|
+
raise
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'aspera/cli/
|
|
3
|
+
require 'aspera/cli/plugins/basic_auth'
|
|
4
4
|
require 'aspera/cli/special_values'
|
|
5
5
|
require 'aspera/nagios'
|
|
6
6
|
require 'aspera/log'
|
|
@@ -10,7 +10,7 @@ require 'xmlsimple'
|
|
|
10
10
|
module Aspera
|
|
11
11
|
module Cli
|
|
12
12
|
module Plugins
|
|
13
|
-
class Orchestrator <
|
|
13
|
+
class Orchestrator < BasicAuth
|
|
14
14
|
STANDARD_PATH = '/aspera/orchestrator'
|
|
15
15
|
TEST_ENDPOINT = 'api/remote_node_ping'
|
|
16
16
|
private_constant :STANDARD_PATH, :TEST_ENDPOINT
|
|
@@ -37,18 +37,20 @@ module Aspera
|
|
|
37
37
|
raise error if error
|
|
38
38
|
return
|
|
39
39
|
end
|
|
40
|
+
end
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
42
|
+
# @param wizard [Wizard] The wizard object
|
|
43
|
+
# @param app_url [Wizard] The wizard object
|
|
44
|
+
# @return [Hash] :preset_value, :test_args
|
|
45
|
+
def wizard(wizard, app_url)
|
|
46
|
+
return {
|
|
47
|
+
preset_value: {
|
|
48
|
+
url: app_url,
|
|
49
|
+
username: options.get_option(:username, mandatory: true),
|
|
50
|
+
password: options.get_option(:password, mandatory: true)
|
|
51
|
+
},
|
|
52
|
+
test_args: 'workflow list'
|
|
53
|
+
}
|
|
52
54
|
end
|
|
53
55
|
|
|
54
56
|
def initialize(**_)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# cspell:ignore trevents
|
|
4
|
-
require 'aspera/cli/
|
|
4
|
+
require 'aspera/cli/plugins/basic_auth'
|
|
5
5
|
require 'aspera/preview/generator'
|
|
6
6
|
require 'aspera/preview/options'
|
|
7
7
|
require 'aspera/preview/utils'
|
|
@@ -9,6 +9,7 @@ require 'aspera/preview/file_types'
|
|
|
9
9
|
require 'aspera/preview/terminal'
|
|
10
10
|
require 'aspera/transfer/spec'
|
|
11
11
|
require 'aspera/persistency_action_once'
|
|
12
|
+
require 'aspera/temp_file_manager'
|
|
12
13
|
require 'aspera/api/node'
|
|
13
14
|
require 'aspera/hash_ext'
|
|
14
15
|
require 'aspera/timer_limiter'
|
|
@@ -20,7 +21,7 @@ require 'securerandom'
|
|
|
20
21
|
module Aspera
|
|
21
22
|
module Cli
|
|
22
23
|
module Plugins
|
|
23
|
-
class Preview <
|
|
24
|
+
class Preview < BasicAuth
|
|
24
25
|
# special tag to identify transfers related to generator
|
|
25
26
|
PREV_GEN_TAG = 'preview_generator'
|
|
26
27
|
# defined by node API: suffix for folder containing previews
|
|
@@ -74,7 +75,6 @@ module Aspera
|
|
|
74
75
|
)
|
|
75
76
|
options.declare(:skip_types, 'Skip types in comma separated list', handler: {o: self, m: :option_skip_types})
|
|
76
77
|
options.declare(:previews_folder, 'Preview folder in storage root', handler: {o: self, m: :option_previews_folder}, default: DEFAULT_PREVIEWS_FOLDER)
|
|
77
|
-
options.declare(:temp_folder, 'Path to temp folder', default: Dir.tmpdir)
|
|
78
78
|
options.declare(:skip_folders, 'List of folder to skip', handler: {o: self, m: :option_skip_folders}, default: [])
|
|
79
79
|
options.declare(:base, 'Basename of output for for test')
|
|
80
80
|
options.declare(:scan_path, 'Subpath in folder id to start scan in (default=/)')
|
|
@@ -100,7 +100,7 @@ module Aspera
|
|
|
100
100
|
|
|
101
101
|
options.parse_options!
|
|
102
102
|
Aspera.assert_type(@option_skip_folders, Array){'skip_folder'}
|
|
103
|
-
@tmp_folder = File.join(
|
|
103
|
+
@tmp_folder = File.join(TempFileManager.instance.global_temp, "#{TMP_DIR_PREFIX}.#{SecureRandom.uuid}")
|
|
104
104
|
FileUtils.mkdir_p(@tmp_folder)
|
|
105
105
|
Log.log.debug{"tmpdir: #{@tmp_folder}"}
|
|
106
106
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# cspell:ignore ascmd zmode zuid zgid fasping
|
|
4
|
-
require 'aspera/cli/
|
|
4
|
+
require 'aspera/cli/plugins/basic_auth'
|
|
5
5
|
require 'aspera/cli/sync_actions'
|
|
6
6
|
require 'aspera/transfer/spec'
|
|
7
7
|
require 'aspera/ascmd'
|
|
@@ -14,7 +14,7 @@ module Aspera
|
|
|
14
14
|
module Cli
|
|
15
15
|
module Plugins
|
|
16
16
|
# Operations on HSTS with SSH/FASP (ascmd/ascp)
|
|
17
|
-
class Server <
|
|
17
|
+
class Server < BasicAuth
|
|
18
18
|
include SyncActions
|
|
19
19
|
|
|
20
20
|
SSH_SCHEME = 'ssh'
|
|
@@ -67,18 +67,20 @@ module Aspera
|
|
|
67
67
|
raise error if error
|
|
68
68
|
return
|
|
69
69
|
end
|
|
70
|
+
end
|
|
70
71
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
72
|
+
# @param wizard [Wizard] The wizard object
|
|
73
|
+
# @param app_url [Wizard] The wizard object
|
|
74
|
+
# @return [Hash] :preset_value, :test_args
|
|
75
|
+
def wizard(wizard, app_url)
|
|
76
|
+
return {
|
|
77
|
+
preset_value: {
|
|
78
|
+
url: app_url,
|
|
79
|
+
username: options.get_option(:username, mandatory: true),
|
|
80
|
+
password: options.get_option(:password, mandatory: true)
|
|
81
|
+
},
|
|
82
|
+
test_args: 'files browse /'
|
|
83
|
+
}
|
|
82
84
|
end
|
|
83
85
|
|
|
84
86
|
def initialize(**_)
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'aspera/cli/plugins/basic_auth'
|
|
3
4
|
require 'aspera/cli/plugins/node'
|
|
4
5
|
require 'aspera/assert'
|
|
5
6
|
module Aspera
|
|
6
7
|
module Cli
|
|
7
8
|
module Plugins
|
|
8
9
|
# Plugin for Aspera Shares v1
|
|
9
|
-
class Shares <
|
|
10
|
+
class Shares < BasicAuth
|
|
10
11
|
# path for node API after base url
|
|
11
12
|
NODE_API_PATH = 'node_api'
|
|
12
13
|
# path for node admin after base url
|
|
@@ -34,18 +35,20 @@ module Aspera
|
|
|
34
35
|
url: address_or_url
|
|
35
36
|
}
|
|
36
37
|
end
|
|
38
|
+
end
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
40
|
+
# @param wizard [Wizard] The wizard object
|
|
41
|
+
# @param app_url [Wizard] The wizard object
|
|
42
|
+
# @return [Hash] :preset_value, :test_args
|
|
43
|
+
def wizard(wizard, app_url)
|
|
44
|
+
return {
|
|
45
|
+
preset_value: {
|
|
46
|
+
url: app_url,
|
|
47
|
+
username: options.get_option(:username, mandatory: true),
|
|
48
|
+
password: options.get_option(:password, mandatory: true)
|
|
49
|
+
},
|
|
50
|
+
test_args: 'files browse /'
|
|
51
|
+
}
|
|
49
52
|
end
|
|
50
53
|
|
|
51
54
|
def initialize(**_)
|
|
@@ -91,9 +94,9 @@ module Aspera
|
|
|
91
94
|
when :node
|
|
92
95
|
return entity_execute(api: api_shares_admin, entity: 'data/nodes')
|
|
93
96
|
when :share
|
|
94
|
-
share_command = options.get_next_command(%i[user_permissions group_permissions].concat(
|
|
97
|
+
share_command = options.get_next_command(%i[user_permissions group_permissions].concat(ALL_OPS))
|
|
95
98
|
case share_command
|
|
96
|
-
when *
|
|
99
|
+
when *ALL_OPS
|
|
97
100
|
return entity_execute(
|
|
98
101
|
api: api_shares_admin,
|
|
99
102
|
entity: 'data/shares',
|
|
@@ -135,7 +138,7 @@ module Aspera
|
|
|
135
138
|
end
|
|
136
139
|
entity_verb = options.get_next_command(entity_commands)
|
|
137
140
|
case entity_verb
|
|
138
|
-
when *
|
|
141
|
+
when *ALL_OPS # list, show, delete, create, modify
|
|
139
142
|
display_fields = entity_type.eql?(:user) ? %w[id username first_name last_name email] : nil
|
|
140
143
|
display_fields.push(:directory_user) if entity_type.eql?(:user) && entities_location.eql?(:all)
|
|
141
144
|
return entity_execute(
|
|
@@ -9,7 +9,7 @@ module Aspera
|
|
|
9
9
|
module Cli
|
|
10
10
|
# Manage command line arguments to provide to Sync::Run, Sync::Database and Sync::Operations
|
|
11
11
|
module SyncActions
|
|
12
|
-
#
|
|
12
|
+
# Translate state id (int) to string
|
|
13
13
|
STATE_STR = (['Nil'] +
|
|
14
14
|
(1..18).map{ |i| "P(#{i})"} +
|
|
15
15
|
%w[Syncd Error Confl Pconf] +
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'aspera/agent/
|
|
3
|
+
require 'aspera/agent/factory'
|
|
4
4
|
require 'aspera/transfer/spec'
|
|
5
5
|
require 'aspera/cli/info'
|
|
6
6
|
require 'aspera/log'
|
|
@@ -9,8 +9,8 @@ require 'aspera/assert'
|
|
|
9
9
|
module Aspera
|
|
10
10
|
module Cli
|
|
11
11
|
# The Transfer agent is a common interface to start a transfer using
|
|
12
|
-
# one of the supported transfer agents
|
|
13
|
-
#
|
|
12
|
+
# one of the supported transfer agents.
|
|
13
|
+
# Provide CLI options to select one of the transfer agents (FASP/ascp client)
|
|
14
14
|
class TransferAgent
|
|
15
15
|
# @args special value for --sources : read file list from arguments
|
|
16
16
|
FILE_LIST_FROM_ARGS = '@args'
|
|
@@ -27,12 +27,11 @@ module Aspera
|
|
|
27
27
|
<%=ts.to_yaml%>
|
|
28
28
|
END_OF_TEMPLATE
|
|
29
29
|
CP4I_REMOTE_HOST_LB = 'N/A'
|
|
30
|
-
# % (formatting bug in eclipse)
|
|
31
30
|
private_constant :FILE_LIST_FROM_ARGS,
|
|
32
31
|
:FILE_LIST_FROM_TRANSFER_SPEC,
|
|
33
32
|
:FILE_LIST_OPTIONS,
|
|
34
33
|
:DEFAULT_TRANSFER_NOTIFY_TEMPLATE
|
|
35
|
-
TRANSFER_AGENTS = Agent::
|
|
34
|
+
TRANSFER_AGENTS = Agent::Factory.instance.list.freeze
|
|
36
35
|
|
|
37
36
|
class << self
|
|
38
37
|
# @return :success if all sessions statuses returned by "start" are success
|
|
@@ -44,7 +43,8 @@ module Aspera
|
|
|
44
43
|
end
|
|
45
44
|
end
|
|
46
45
|
|
|
47
|
-
# @param
|
|
46
|
+
# @param opt_mgr [Manager] Option manager
|
|
47
|
+
# @param config_plugin [Config] Config plugin
|
|
48
48
|
def initialize(opt_mgr, config_plugin)
|
|
49
49
|
@opt_mgr = opt_mgr
|
|
50
50
|
@config = config_plugin
|
|
@@ -82,18 +82,20 @@ module Aspera
|
|
|
82
82
|
|
|
83
83
|
def option_transfer_spec; @transfer_spec_command_line; end
|
|
84
84
|
|
|
85
|
-
#
|
|
85
|
+
# Multiple option are merged
|
|
86
|
+
# @param value [Hash] Transfer spec
|
|
86
87
|
def option_transfer_spec=(value)
|
|
87
88
|
Aspera.assert_type(value, Hash){'ts'}
|
|
88
89
|
@transfer_spec_command_line.deep_merge!(value)
|
|
89
90
|
end
|
|
90
91
|
|
|
91
|
-
#
|
|
92
|
+
# Add other transfer spec parameters
|
|
92
93
|
def option_transfer_spec_deep_merge(value); @transfer_spec_command_line.deep_merge!(value); end
|
|
93
94
|
|
|
94
95
|
attr_reader :transfer_info
|
|
95
96
|
|
|
96
|
-
#
|
|
97
|
+
# Multiple option are merged
|
|
98
|
+
# @param value [Hash]
|
|
97
99
|
def transfer_info=(value)
|
|
98
100
|
@transfer_info.deep_merge!(value)
|
|
99
101
|
end
|
|
@@ -103,19 +105,20 @@ module Aspera
|
|
|
103
105
|
end
|
|
104
106
|
|
|
105
107
|
# analyze options and create new agent if not already created or set
|
|
106
|
-
# TODO: make a Factory pattern
|
|
107
108
|
def agent_instance
|
|
108
109
|
return @agent unless @agent.nil?
|
|
109
110
|
agent_type = @opt_mgr.get_option(:transfer, mandatory: true)
|
|
110
111
|
# set keys as symbols
|
|
111
112
|
agent_options = @opt_mgr.get_option(:transfer_info).symbolize_keys
|
|
113
|
+
agent_options[:progress] = @config.progress_bar
|
|
114
|
+
agent_options[:config_dir] = @config.main_folder
|
|
112
115
|
# special cases
|
|
113
116
|
case agent_type
|
|
114
117
|
when :node
|
|
115
|
-
if agent_options.
|
|
118
|
+
if !agent_options.key?(:url)
|
|
116
119
|
param_set_name = @config.get_plugin_default_config_name(:node)
|
|
117
120
|
raise Cli::BadArgument, "No default node configured. Please specify #{Manager.option_name_to_line(:transfer_info)}" if param_set_name.nil?
|
|
118
|
-
agent_options
|
|
121
|
+
agent_options.merge!(@config.preset_by_name(param_set_name).symbolize_keys)
|
|
119
122
|
end
|
|
120
123
|
when :direct
|
|
121
124
|
# by default do not display ascp native progress bar
|
|
@@ -129,16 +132,15 @@ module Aspera
|
|
|
129
132
|
agent_options[:url] = @httpgw_url_lambda.call
|
|
130
133
|
end
|
|
131
134
|
end
|
|
132
|
-
agent_options[:progress] = @config.progress_bar
|
|
133
135
|
# get agent instance
|
|
134
|
-
self.agent_instance = Agent::
|
|
136
|
+
self.agent_instance = Agent::Factory.instance.create(agent_type, agent_options)
|
|
135
137
|
Log.log.debug{"transfer agent is a #{@agent.class}"}
|
|
136
138
|
return @agent
|
|
137
139
|
end
|
|
138
140
|
|
|
139
|
-
#
|
|
140
|
-
#
|
|
141
|
-
#
|
|
141
|
+
# Get destination folder
|
|
142
|
+
# @param direction [String] `send`` or `receive``
|
|
143
|
+
# @return [String] Destination folder for transfers (with default based on direction)
|
|
142
144
|
def destination_folder(direction)
|
|
143
145
|
dest_folder = @opt_mgr.get_option(:to_folder)
|
|
144
146
|
# do not expand path, if user wants to expand path: user @path:
|
|
@@ -161,12 +163,14 @@ module Aspera
|
|
|
161
163
|
end
|
|
162
164
|
end
|
|
163
165
|
|
|
166
|
+
# @param httpgw_url_proc [Proc]
|
|
164
167
|
def httpgw_url_cb=(httpgw_url_proc)
|
|
165
168
|
Aspera.assert_type(httpgw_url_proc, Proc){'httpgw_url_cb'}
|
|
166
169
|
@httpgw_url_lambda = httpgw_url_proc
|
|
167
170
|
end
|
|
168
171
|
|
|
169
|
-
#
|
|
172
|
+
# Transform the list of paths to a list of hash with source/dest
|
|
173
|
+
# @param file_list [Array]
|
|
170
174
|
def list_to_paths(file_list)
|
|
171
175
|
source_type = @opt_mgr.get_option(:src_type, mandatory: true)
|
|
172
176
|
case source_type
|
|
@@ -220,9 +224,9 @@ module Aspera
|
|
|
220
224
|
return @transfer_paths
|
|
221
225
|
end
|
|
222
226
|
|
|
223
|
-
#
|
|
227
|
+
# Start a transfer and wait for completion, plugins shall use this method
|
|
224
228
|
# @param transfer_spec [Hash]
|
|
225
|
-
# @param rest_token
|
|
229
|
+
# @param rest_token [Rest] if oauth token regeneration supported
|
|
226
230
|
def start(transfer_spec, rest_token: nil)
|
|
227
231
|
# check parameters
|
|
228
232
|
Aspera.assert_type(transfer_spec, Hash){'transfer_spec'}
|
|
@@ -13,7 +13,7 @@ module Aspera
|
|
|
13
13
|
class TransferProgress
|
|
14
14
|
def initialize
|
|
15
15
|
@progress_bar = nil
|
|
16
|
-
#
|
|
16
|
+
# Key is session id
|
|
17
17
|
@sessions = {}
|
|
18
18
|
@completed = false
|
|
19
19
|
@title = nil
|
|
@@ -42,21 +42,21 @@ module Aspera
|
|
|
42
42
|
progress_provided = false
|
|
43
43
|
case type
|
|
44
44
|
when :sessions_init
|
|
45
|
-
#
|
|
45
|
+
# Give opportunity to show progress of initialization with multiple status
|
|
46
46
|
Aspera.assert(session_id.nil?)
|
|
47
47
|
Aspera.assert_type(info, String)
|
|
48
|
-
#
|
|
48
|
+
# Initialization of progress bar
|
|
49
49
|
@title = info
|
|
50
50
|
when :session_start
|
|
51
51
|
Aspera.assert_type(session_id, String)
|
|
52
52
|
Aspera.assert(info.nil?)
|
|
53
53
|
raise "Session #{session_id} already started" if @sessions[session_id]
|
|
54
54
|
@sessions[session_id] = {
|
|
55
|
-
job_size: 0, #
|
|
55
|
+
job_size: 0, # Total size of transfer (pre-calc)
|
|
56
56
|
current: 0,
|
|
57
57
|
running: true
|
|
58
58
|
}
|
|
59
|
-
#
|
|
59
|
+
# Remove last pre-start message if any
|
|
60
60
|
@title = nil
|
|
61
61
|
when :session_size
|
|
62
62
|
Aspera.assert_type(session_id, String)
|
|
@@ -77,7 +77,7 @@ module Aspera
|
|
|
77
77
|
when :session_end
|
|
78
78
|
Aspera.assert_type(session_id, String)
|
|
79
79
|
Aspera.assert(info.nil?)
|
|
80
|
-
#
|
|
80
|
+
# A session may be too short and finish before it has been started
|
|
81
81
|
@sessions[session_id][:running] = false if @sessions[session_id].is_a?(Hash)
|
|
82
82
|
when :end
|
|
83
83
|
Aspera.assert(session_id.nil?)
|
data/lib/aspera/cli/version.rb
CHANGED