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,92 +1,91 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# cspell:ignore snid fnid bidi ssync asyncs rund asnodeadmin mkfile mklink asperabrowser asperabrowserurl watchfolders watchfolderd entsrv
|
|
3
4
|
require 'aspera/cli/basic_auth_plugin'
|
|
4
|
-
require 'aspera/cli/
|
|
5
|
+
require 'aspera/cli/sync_actions'
|
|
6
|
+
require 'aspera/fasp/transfer_spec'
|
|
5
7
|
require 'aspera/nagios'
|
|
6
8
|
require 'aspera/hash_ext'
|
|
7
9
|
require 'aspera/id_generator'
|
|
8
10
|
require 'aspera/node'
|
|
9
11
|
require 'aspera/aoc'
|
|
10
|
-
require 'aspera/
|
|
11
|
-
require 'aspera/
|
|
12
|
+
require 'aspera/oauth'
|
|
13
|
+
require 'aspera/node_simulator'
|
|
14
|
+
require 'aspera/assert'
|
|
12
15
|
require 'base64'
|
|
13
16
|
require 'zlib'
|
|
14
17
|
|
|
15
18
|
module Aspera
|
|
16
19
|
module Cli
|
|
17
20
|
module Plugins
|
|
18
|
-
class SyncSpecGen3
|
|
19
|
-
def initialize(api_node)
|
|
20
|
-
@api_node = api_node
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def transfer_spec(direction, local_path, remote_path)
|
|
24
|
-
# empty transfer spec for authorization request
|
|
25
|
-
direction_sym = direction.to_sym
|
|
26
|
-
request_transfer_spec = {
|
|
27
|
-
type: Aspera::Sync::DIRECTION_TO_REQUEST_TYPE[direction_sym],
|
|
28
|
-
paths: {
|
|
29
|
-
source: remote_path,
|
|
30
|
-
destination: local_path
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
# add fixed parameters if any (for COS)
|
|
34
|
-
@api_node.add_tspec_info(request_transfer_spec) if @api_node.respond_to?(:add_tspec_info)
|
|
35
|
-
# prepare payload for single request
|
|
36
|
-
setup_payload = {transfer_requests: [{transfer_request: request_transfer_spec}]}
|
|
37
|
-
# only one request, so only one answer
|
|
38
|
-
transfer_spec = @api_node.create('files/sync_setup', setup_payload)[:data]['transfer_specs'].first['transfer_spec']
|
|
39
|
-
# API returns null tag... but async does not like it
|
|
40
|
-
transfer_spec.delete_if{ |_k, v| v.nil? }
|
|
41
|
-
# delete this part, as the returned value contains only destination, and not sources
|
|
42
|
-
# transfer_spec.delete('paths') if command.eql?(:upload)
|
|
43
|
-
Log.dump(:ts, transfer_spec)
|
|
44
|
-
return transfer_spec
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
class SyncSpecGen4
|
|
49
|
-
def initialize(api_node, top_file_id)
|
|
50
|
-
@api_node = api_node
|
|
51
|
-
@top_file_id = top_file_id
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def transfer_spec(direction, local_path, remote_path)
|
|
55
|
-
# remote is specified by option to_folder
|
|
56
|
-
apifid = @api_node.resolve_api_fid(@top_file_id, remote_path)
|
|
57
|
-
transfer_spec = apifid[:api].transfer_spec_gen4(apifid[:file_id], Fasp::TransferSpec::DIRECTION_SEND)
|
|
58
|
-
Log.dump(:ts, transfer_spec)
|
|
59
|
-
return transfer_spec
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
21
|
class Node < Aspera::Cli::BasicAuthPlugin
|
|
22
|
+
include SyncActions
|
|
64
23
|
class << self
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
24
|
+
@@node_options_declared = false # rubocop:disable Style/ClassVars
|
|
25
|
+
def application_name
|
|
26
|
+
'HSTS Node API'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def detect(address_or_url)
|
|
30
|
+
urls = if address_or_url.match?(%r{^[a-z]{1,6}://})
|
|
31
|
+
[address_or_url]
|
|
32
|
+
else
|
|
33
|
+
[
|
|
34
|
+
"https://#{address_or_url}",
|
|
35
|
+
"https://#{address_or_url}:9092",
|
|
36
|
+
"http://#{address_or_url}:9091"
|
|
37
|
+
]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
urls.each do |base_url|
|
|
41
|
+
next unless base_url.match?('https?://')
|
|
42
|
+
api = Rest.new(base_url: base_url)
|
|
43
|
+
test_endpoint = 'ping'
|
|
44
|
+
result = api.call(operation: 'GET', subpath: test_endpoint)
|
|
45
|
+
next unless result[:http].body.eql?('')
|
|
46
|
+
url_length = -2 - test_endpoint.length
|
|
47
|
+
return {
|
|
48
|
+
url: result[:http].uri.to_s[0..url_length]
|
|
49
|
+
}
|
|
50
|
+
rescue StandardError => e
|
|
51
|
+
Log.log.debug{"detect error: #{e}"}
|
|
70
52
|
end
|
|
71
53
|
return nil
|
|
72
54
|
end
|
|
73
55
|
|
|
74
|
-
def
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
56
|
+
def wizard(object:, private_key_path: nil, pub_key_pem: nil)
|
|
57
|
+
options = object.options
|
|
58
|
+
return {
|
|
59
|
+
preset_value: {
|
|
60
|
+
url: options.get_option(:url, mandatory: true),
|
|
61
|
+
username: options.get_option(:username, mandatory: true),
|
|
62
|
+
password: options.get_option(:password, mandatory: true)
|
|
63
|
+
},
|
|
64
|
+
test_args: 'info'
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def declare_options(options, force: false)
|
|
69
|
+
return if @@node_options_declared && !force
|
|
70
|
+
@@node_options_declared = true # rubocop:disable Style/ClassVars
|
|
71
|
+
options.declare(:validator, 'Identifier of validator (optional for central)')
|
|
72
|
+
options.declare(:asperabrowserurl, 'URL for simple aspera web ui', default: 'https://asperabrowser.mybluemix.net')
|
|
73
|
+
options.declare(:sync_name, 'Sync name')
|
|
74
|
+
options.declare(
|
|
75
|
+
:default_ports, 'Use standard FASP ports or get from node api (gen4)', values: :bool, default: :yes,
|
|
76
|
+
handler: {o: Aspera::Node, m: :use_standard_ports})
|
|
77
|
+
options.declare(:root_id, 'File id of top folder if using bearer tokens')
|
|
78
|
+
SyncActions.declare_options(options)
|
|
79
|
+
options.parse_options!
|
|
81
80
|
end
|
|
82
81
|
end
|
|
83
82
|
|
|
84
83
|
# spellchecker: disable
|
|
85
84
|
# SOAP API call to test central API
|
|
86
|
-
CENTRAL_SOAP_API_TEST = '<?xml version="1.0" encoding="UTF-8"?>'\
|
|
87
|
-
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="urn:Aspera:XML:FASPSessionNET:2009/11:Types">'\
|
|
88
|
-
'<soapenv:Header></soapenv:Header>'\
|
|
89
|
-
'<soapenv:Body><typ:GetSessionInfoRequest><SessionFilter><SessionStatus>running</SessionStatus></SessionFilter></typ:GetSessionInfoRequest></soapenv:Body>'\
|
|
85
|
+
CENTRAL_SOAP_API_TEST = '<?xml version="1.0" encoding="UTF-8"?>' \
|
|
86
|
+
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="urn:Aspera:XML:FASPSessionNET:2009/11:Types">' \
|
|
87
|
+
'<soapenv:Header></soapenv:Header>' \
|
|
88
|
+
'<soapenv:Body><typ:GetSessionInfoRequest><SessionFilter><SessionStatus>running</SessionStatus></SessionFilter></typ:GetSessionInfoRequest></soapenv:Body>' \
|
|
90
89
|
'</soapenv:Envelope>'
|
|
91
90
|
# spellchecker: enable
|
|
92
91
|
|
|
@@ -94,17 +93,17 @@ module Aspera
|
|
|
94
93
|
SEARCH_REMOVE_FIELDS = %w[basename permissions].freeze
|
|
95
94
|
|
|
96
95
|
# actions in execute_command_gen3
|
|
97
|
-
COMMANDS_GEN3 = %i[search space mkdir mklink mkfile rename delete browse upload download sync]
|
|
96
|
+
COMMANDS_GEN3 = %i[search space mkdir mklink mkfile rename delete browse upload download http_node_download sync]
|
|
98
97
|
|
|
99
98
|
BASE_ACTIONS = %i[api_details].concat(COMMANDS_GEN3).freeze
|
|
100
99
|
|
|
101
|
-
SPECIAL_ACTIONS = %i[health events info license].freeze
|
|
100
|
+
SPECIAL_ACTIONS = %i[health events info slash license].freeze
|
|
102
101
|
|
|
103
102
|
# actions available in v3 in gen4
|
|
104
|
-
V3_IN_V4_ACTIONS = %i[
|
|
103
|
+
V3_IN_V4_ACTIONS = %i[access_keys].concat(BASE_ACTIONS).concat(SPECIAL_ACTIONS).freeze
|
|
105
104
|
|
|
106
105
|
# actions used commonly when a node is involved
|
|
107
|
-
COMMON_ACTIONS = %i[
|
|
106
|
+
COMMON_ACTIONS = %i[access_keys].concat(BASE_ACTIONS).concat(SPECIAL_ACTIONS).freeze
|
|
108
107
|
|
|
109
108
|
private_constant(*%i[CENTRAL_SOAP_API_TEST SEARCH_REMOVE_FIELDS BASE_ACTIONS SPECIAL_ACTIONS V3_IN_V4_ACTIONS COMMON_ACTIONS])
|
|
110
109
|
|
|
@@ -114,26 +113,22 @@ module Aspera
|
|
|
114
113
|
# commands for execute_command_gen4
|
|
115
114
|
COMMANDS_GEN4 = %i[mkdir rename delete upload download sync http_node_download show modify permission thumbnail v3].concat(NODE4_READ_ACTIONS).freeze
|
|
116
115
|
|
|
117
|
-
COMMANDS_COS = %i[upload download info
|
|
116
|
+
COMMANDS_COS = %i[upload download info access_keys api_details transfer].freeze
|
|
118
117
|
COMMANDS_SHARES = (BASE_ACTIONS - %i[search]).freeze
|
|
119
118
|
COMMANDS_FASPEX = COMMON_ACTIONS
|
|
120
119
|
|
|
121
|
-
def initialize(env)
|
|
120
|
+
def initialize(env, api: nil)
|
|
122
121
|
super(env)
|
|
123
|
-
|
|
124
|
-
return if env[:man_only]
|
|
122
|
+
Node.declare_options(options, force: env[:all_manuals])
|
|
125
123
|
@api_node =
|
|
126
|
-
if
|
|
124
|
+
if !api.nil? || env[:all_manuals]
|
|
127
125
|
# this can be Aspera::Node or Aspera::Rest (shares)
|
|
128
|
-
|
|
129
|
-
elsif options.get_option(:password, mandatory: true)
|
|
126
|
+
api
|
|
127
|
+
elsif Oauth.bearer?(options.get_option(:password, mandatory: true))
|
|
130
128
|
# info is provided like node_info of aoc
|
|
131
129
|
Aspera::Node.new(params: {
|
|
132
130
|
base_url: options.get_option(:url, mandatory: true),
|
|
133
|
-
headers:
|
|
134
|
-
Aspera::Node::HEADER_X_ASPERA_ACCESS_KEY => options.get_option(:username, mandatory: true),
|
|
135
|
-
'Authorization' => options.get_option(:password, mandatory: true)
|
|
136
|
-
}
|
|
131
|
+
headers: Aspera::Node.bearer_headers(options.get_option(:password, mandatory: true))
|
|
137
132
|
})
|
|
138
133
|
else
|
|
139
134
|
# this is normal case
|
|
@@ -147,26 +142,6 @@ module Aspera
|
|
|
147
142
|
end
|
|
148
143
|
end
|
|
149
144
|
|
|
150
|
-
def c_textify_browse(table_data)
|
|
151
|
-
return table_data.map do |i|
|
|
152
|
-
i['permissions'] = i['permissions'].map { |x| x['name'] }.join(',')
|
|
153
|
-
i
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
# key/value is defined in main in hash_table
|
|
158
|
-
def c_textify_bool_list_result(list, name_list)
|
|
159
|
-
list.each_index do |i|
|
|
160
|
-
next unless name_list.include?(list[i]['key'])
|
|
161
|
-
list[i]['value'].each do |item|
|
|
162
|
-
list.push({'key' => item['name'], 'value' => item['value']})
|
|
163
|
-
end
|
|
164
|
-
list.delete_at(i)
|
|
165
|
-
# continue at same index because we delete current one
|
|
166
|
-
redo
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
|
|
170
145
|
# reduce the path from a result on given named column
|
|
171
146
|
def c_result_remove_prefix_path(result, column, path_prefix)
|
|
172
147
|
if !path_prefix.nil?
|
|
@@ -222,7 +197,7 @@ module Aspera
|
|
|
222
197
|
when :search
|
|
223
198
|
search_root = get_next_arg_add_prefix(prefix_path, 'search root')
|
|
224
199
|
parameters = {'path' => search_root}
|
|
225
|
-
other_options =
|
|
200
|
+
other_options = query_option
|
|
226
201
|
parameters.merge!(other_options) unless other_options.nil?
|
|
227
202
|
resp = @api_node.create('files/search', parameters)
|
|
228
203
|
result = { type: :object_list, data: resp[:data]['items']}
|
|
@@ -268,17 +243,40 @@ module Aspera
|
|
|
268
243
|
# if there is no items
|
|
269
244
|
case send_result['self']['type']
|
|
270
245
|
when 'directory', 'container' # directory: node, container: shares
|
|
271
|
-
result = { data: send_result['items'], type: :object_list
|
|
246
|
+
result = { data: send_result['items'], type: :object_list }
|
|
272
247
|
formatter.display_item_count(send_result['item_count'], send_result['total_count'])
|
|
273
248
|
else # 'file','symbolic_link'
|
|
274
249
|
result = { data: send_result['self'], type: :single_object}
|
|
275
|
-
# result={ data: [send_result['self']] , type: :object_list, textify: lambda { |table_data| c_textify_browse(table_data) } }
|
|
276
|
-
# raise "unknown type: #{send_result['self']['type']}"
|
|
277
250
|
end
|
|
278
251
|
return c_result_remove_prefix_path(result, 'path', prefix_path)
|
|
279
252
|
when :sync
|
|
280
|
-
|
|
281
|
-
|
|
253
|
+
return execute_sync_action do |sync_direction, local_path, remote_path|
|
|
254
|
+
# Gen3 API
|
|
255
|
+
# empty transfer spec for authorization request
|
|
256
|
+
request_transfer_spec = {
|
|
257
|
+
type: case sync_direction
|
|
258
|
+
when :push then :sync_upload
|
|
259
|
+
when :pull then :sync_download
|
|
260
|
+
when :bidi then :sync
|
|
261
|
+
end,
|
|
262
|
+
paths: [{
|
|
263
|
+
source: remote_path,
|
|
264
|
+
destination: local_path
|
|
265
|
+
}]
|
|
266
|
+
}
|
|
267
|
+
# add fixed parameters if any (for COS)
|
|
268
|
+
@api_node.add_tspec_info(request_transfer_spec) if @api_node.respond_to?(:add_tspec_info)
|
|
269
|
+
# prepare payload for single request
|
|
270
|
+
setup_payload = {transfer_requests: [{transfer_request: request_transfer_spec}]}
|
|
271
|
+
# only one request, so only one answer
|
|
272
|
+
transfer_spec = @api_node.create('files/sync_setup', setup_payload)[:data]['transfer_specs'].first['transfer_spec']
|
|
273
|
+
# API returns null tag... but async does not like it
|
|
274
|
+
transfer_spec.delete_if{ |_k, v| v.nil? }
|
|
275
|
+
# delete this part, as the returned value contains only destination, and not sources
|
|
276
|
+
# transfer_spec.delete('paths') if command.eql?(:upload)
|
|
277
|
+
Log.log.debug{Log.dump(:ts, transfer_spec)}
|
|
278
|
+
transfer_spec
|
|
279
|
+
end
|
|
282
280
|
when :upload, :download
|
|
283
281
|
# empty transfer spec for authorization request
|
|
284
282
|
request_transfer_spec = {}
|
|
@@ -297,8 +295,16 @@ module Aspera
|
|
|
297
295
|
# delete this part, as the returned value contains only destination, and not sources
|
|
298
296
|
transfer_spec.delete('paths') if command.eql?(:upload)
|
|
299
297
|
return Main.result_transfer(transfer.start(transfer_spec))
|
|
298
|
+
when :http_node_download
|
|
299
|
+
remote_path = get_next_arg_add_prefix(prefix_path, 'remote path')
|
|
300
|
+
file_name = File.basename(remote_path)
|
|
301
|
+
@api_node.call(
|
|
302
|
+
operation: 'GET',
|
|
303
|
+
subpath: "files/#{URI.encode_www_form_component(remote_path)}/contents",
|
|
304
|
+
save_to_file: File.join(transfer.destination_folder(Fasp::TransferSpec::DIRECTION_RECEIVE), file_name))
|
|
305
|
+
return Main.result_status("downloaded: #{file_name}")
|
|
300
306
|
end
|
|
301
|
-
|
|
307
|
+
error_unreachable_line
|
|
302
308
|
end
|
|
303
309
|
|
|
304
310
|
# common API to node and Shares
|
|
@@ -307,20 +313,37 @@ module Aspera
|
|
|
307
313
|
case command
|
|
308
314
|
when *COMMANDS_GEN3
|
|
309
315
|
execute_command_gen3(command, prefix_path)
|
|
310
|
-
when :
|
|
311
|
-
ak_command = options.get_next_command([
|
|
316
|
+
when :access_keys
|
|
317
|
+
ak_command = options.get_next_command(%i[do set_bearer_key].concat(Plugin::ALL_OPS))
|
|
312
318
|
case ak_command
|
|
313
|
-
when *Plugin::ALL_OPS
|
|
319
|
+
when *Plugin::ALL_OPS
|
|
320
|
+
return entity_command(ak_command, @api_node, 'access_keys') do |field, value|
|
|
321
|
+
raise 'only selector: %id:self' unless field.eql?('id') && value.eql?('self')
|
|
322
|
+
@api_node.read('access_keys/self')[:data]['id']
|
|
323
|
+
end
|
|
314
324
|
when :do
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
325
|
+
access_key_id = options.get_next_argument('access key id')
|
|
326
|
+
root_file_id = options.get_option(:root_id)
|
|
327
|
+
if root_file_id.nil?
|
|
328
|
+
ak_info = @api_node.read("access_keys/#{access_key_id}")[:data]
|
|
329
|
+
# change API credentials if different access key
|
|
330
|
+
if !access_key_id.eql?('self')
|
|
331
|
+
@api_node.params[:auth][:username] = ak_info['id']
|
|
332
|
+
@api_node.params[:auth][:password] = config.lookup_secret(url: @api_node.params[:base_url], username: ak_info['id'], mandatory: true)
|
|
333
|
+
end
|
|
334
|
+
root_file_id = ak_info['root_file_id']
|
|
321
335
|
end
|
|
322
336
|
command_repo = options.get_next_command(COMMANDS_GEN4)
|
|
323
|
-
return execute_command_gen4(command_repo,
|
|
337
|
+
return execute_command_gen4(command_repo, root_file_id)
|
|
338
|
+
when :set_bearer_key
|
|
339
|
+
access_key_id = options.get_next_argument('access key id')
|
|
340
|
+
access_key_id = @api_node.read('access_keys/self')[:data]['id'] if access_key_id.eql?('self')
|
|
341
|
+
bearer_key_pem = options.get_next_argument('public or private RSA key PEM value', type: String)
|
|
342
|
+
key = OpenSSL::PKey.read(bearer_key_pem)
|
|
343
|
+
key = key.public_key if key.private?
|
|
344
|
+
bearer_key_pem = key.to_pem
|
|
345
|
+
@api_node.update("access_keys/#{access_key_id}", {token_verification_key: bearer_key_pem})
|
|
346
|
+
return Main.result_status('public key updated')
|
|
324
347
|
end
|
|
325
348
|
when :health
|
|
326
349
|
nagios = Nagios.new
|
|
@@ -345,10 +368,13 @@ module Aspera
|
|
|
345
368
|
return nagios.result
|
|
346
369
|
when :events
|
|
347
370
|
events = @api_node.read('events', query_read_delete)[:data]
|
|
348
|
-
return { type: :object_list, data: events}
|
|
371
|
+
return { type: :object_list, data: events, fields: ->(f){!f.start_with?('data')} }
|
|
349
372
|
when :info
|
|
350
373
|
nd_info = @api_node.read('info')[:data]
|
|
351
|
-
return { type: :single_object, data: nd_info
|
|
374
|
+
return { type: :single_object, data: nd_info}
|
|
375
|
+
when :slash
|
|
376
|
+
nd_info = @api_node.read('')[:data]
|
|
377
|
+
return { type: :single_object, data: nd_info}
|
|
352
378
|
when :license
|
|
353
379
|
# requires: asnodeadmin -mu <node user> --acl-add=internal --internal
|
|
354
380
|
node_license = @api_node.read('license')[:data]
|
|
@@ -364,7 +390,7 @@ module Aspera
|
|
|
364
390
|
# @return [Hash] api and main file id for given path or id
|
|
365
391
|
# Allows to specify a file by its path or by its id on the node
|
|
366
392
|
def apifid_from_next_arg(top_file_id)
|
|
367
|
-
file_path = instance_identifier(description: 'path or id') do |attribute, value|
|
|
393
|
+
file_path = instance_identifier(description: 'path or %id:<id>') do |attribute, value|
|
|
368
394
|
raise 'Only selection "id" is supported (file id)' unless attribute.eql?('id')
|
|
369
395
|
# directly return result for method
|
|
370
396
|
return {api: @api_node, file_id: value}
|
|
@@ -380,14 +406,14 @@ module Aspera
|
|
|
380
406
|
command_legacy = options.get_next_command(V3_IN_V4_ACTIONS)
|
|
381
407
|
# TODO: shall we support all methods here ? what if there is a link ?
|
|
382
408
|
apifid = @api_node.resolve_api_fid(top_file_id, '')
|
|
383
|
-
return Node.new(@agents
|
|
409
|
+
return Node.new(@agents, api: apifid[:api]).execute_action(command_legacy)
|
|
384
410
|
when :node_info, :bearer_token_node
|
|
385
411
|
apifid = @api_node.resolve_api_fid(top_file_id, options.get_next_argument('path'))
|
|
386
412
|
result = {
|
|
387
413
|
url: apifid[:api].params[:base_url],
|
|
388
414
|
root_id: apifid[:file_id]
|
|
389
415
|
}
|
|
390
|
-
|
|
416
|
+
assert_values(apifid[:api].params[:auth][:type], %i[basic oauth2])
|
|
391
417
|
case apifid[:api].params[:auth][:type]
|
|
392
418
|
when :basic
|
|
393
419
|
result[:username] = apifid[:api].params[:auth][:username]
|
|
@@ -395,10 +421,11 @@ module Aspera
|
|
|
395
421
|
when :oauth2
|
|
396
422
|
result[:username] = apifid[:api].params[:headers][Aspera::Node::HEADER_X_ASPERA_ACCESS_KEY]
|
|
397
423
|
result[:password] = apifid[:api].oauth_token
|
|
398
|
-
else
|
|
424
|
+
else error_unreachable_line
|
|
399
425
|
end
|
|
400
426
|
return {type: :single_object, data: result} if command_repo.eql?(:node_info)
|
|
401
|
-
|
|
427
|
+
# check format of bearer token
|
|
428
|
+
Oauth.bearer_extract(result[:password])
|
|
402
429
|
return Main.result_status(result[:password])
|
|
403
430
|
when :browse
|
|
404
431
|
apifid = @api_node.resolve_api_fid(top_file_id, options.get_next_argument('path'))
|
|
@@ -413,7 +440,7 @@ module Aspera
|
|
|
413
440
|
return {type: :object_list, data: items, fields: %w[name type recursive_size size modified_time access_level]}
|
|
414
441
|
when :find
|
|
415
442
|
apifid = @api_node.resolve_api_fid(top_file_id, options.get_next_argument('path'))
|
|
416
|
-
test_block = Aspera::Node.
|
|
443
|
+
test_block = Aspera::Node.file_matcher_from_argument(options)
|
|
417
444
|
return {type: :object_list, data: @api_node.find_files(apifid[:file_id], test_block), fields: ['path']}
|
|
418
445
|
when :mkdir
|
|
419
446
|
containing_folder_path = options.get_next_argument('path').split(Aspera::Node::PATH_SEPARATOR)
|
|
@@ -428,15 +455,27 @@ module Aspera
|
|
|
428
455
|
result = apifid[:api].update("files/#{apifid[:file_id]}", {name: newname})[:data]
|
|
429
456
|
return Main.result_status("renamed to #{newname}")
|
|
430
457
|
when :delete
|
|
431
|
-
return do_bulk_operation(
|
|
432
|
-
raise "expecting String (path), got #{l_path.class.name} (#{l_path})" unless l_path.is_a?(String)
|
|
458
|
+
return do_bulk_operation(command: command_repo, descr: 'path', values: String, id_result: 'path') do |l_path|
|
|
433
459
|
apifid = @api_node.resolve_api_fid(top_file_id, l_path)
|
|
434
460
|
result = apifid[:api].delete("files/#{apifid[:file_id]}")[:data]
|
|
435
461
|
{'path' => l_path}
|
|
436
462
|
end
|
|
437
463
|
when :sync
|
|
438
|
-
|
|
439
|
-
|
|
464
|
+
return execute_sync_action do |sync_direction, _local_path, remote_path|
|
|
465
|
+
# Gen4 API
|
|
466
|
+
# direction is push pull, bidi
|
|
467
|
+
assert_values(sync_direction, %i[push pull bidi])
|
|
468
|
+
ts_direction = case sync_direction
|
|
469
|
+
when :push, :bidi then Fasp::TransferSpec::DIRECTION_SEND
|
|
470
|
+
when :pull then Fasp::TransferSpec::DIRECTION_RECEIVE
|
|
471
|
+
else error_unreachable_line
|
|
472
|
+
end
|
|
473
|
+
# remote is specified by option to_folder
|
|
474
|
+
apifid = @api_node.resolve_api_fid(top_file_id, remote_path)
|
|
475
|
+
transfer_spec = apifid[:api].transfer_spec_gen4(apifid[:file_id], ts_direction)
|
|
476
|
+
Log.log.debug{Log.dump(:ts, transfer_spec)}
|
|
477
|
+
transfer_spec
|
|
478
|
+
end
|
|
440
479
|
when :upload
|
|
441
480
|
apifid = @api_node.resolve_api_fid(top_file_id, transfer.destination_folder(Fasp::TransferSpec::DIRECTION_SEND))
|
|
442
481
|
return Main.result_transfer(transfer.start(apifid[:api].transfer_spec_gen4(apifid[:file_id], Fasp::TransferSpec::DIRECTION_SEND)))
|
|
@@ -475,7 +514,7 @@ module Aspera
|
|
|
475
514
|
source_paths = [{'source' => source_folder.pop}]
|
|
476
515
|
source_folder = source_folder.join(Aspera::Node::PATH_SEPARATOR)
|
|
477
516
|
end
|
|
478
|
-
raise
|
|
517
|
+
raise Cli::BadArgument, 'one file at a time only in HTTP mode' if source_paths.length > 1
|
|
479
518
|
file_name = source_paths.first['source']
|
|
480
519
|
apifid = @api_node.resolve_api_fid(top_file_id, File.join(source_folder, file_name))
|
|
481
520
|
apifid[:api].call(
|
|
@@ -499,8 +538,7 @@ module Aspera
|
|
|
499
538
|
subpath: "files/#{apifid[:file_id]}/preview",
|
|
500
539
|
headers: {'Accept' => 'image/png'}
|
|
501
540
|
)
|
|
502
|
-
|
|
503
|
-
return Main.result_status(Preview::Terminal.build(result[:http].body, reserved_lines: 3))
|
|
541
|
+
return Main.result_picture_in_terminal(options, result[:http].body)
|
|
504
542
|
when :permission
|
|
505
543
|
apifid = apifid_from_next_arg(top_file_id)
|
|
506
544
|
command_perm = options.get_next_command(%i[list create delete])
|
|
@@ -514,10 +552,8 @@ module Aspera
|
|
|
514
552
|
items = apifid[:api].read('permissions', list_options)[:data]
|
|
515
553
|
return {type: :object_list, data: items}
|
|
516
554
|
when :delete
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
# TODO: notify event ?
|
|
520
|
-
apifid[:api].delete("permissions/#{perm_id}")
|
|
555
|
+
return do_bulk_operation(command: command_perm, descr: 'identifier', values: :identifier) do |one_id|
|
|
556
|
+
apifid[:api].delete("permissions/#{one_id}")
|
|
521
557
|
# notify application of deletion
|
|
522
558
|
the_app[:api].permissions_send_event(created_data: created_data, app_info: the_app, types: ['permission.deleted']) unless the_app.nil?
|
|
523
559
|
{'id' => one_id}
|
|
@@ -535,11 +571,11 @@ module Aspera
|
|
|
535
571
|
# notify application of creation
|
|
536
572
|
the_app[:api].permissions_send_event(created_data: created_data, app_info: the_app) unless the_app.nil?
|
|
537
573
|
return { type: :single_object, data: created_data}
|
|
538
|
-
else
|
|
574
|
+
else error_unreachable_line
|
|
539
575
|
end
|
|
540
|
-
else
|
|
576
|
+
else error_unreachable_line
|
|
541
577
|
end # command_repo
|
|
542
|
-
|
|
578
|
+
error_unreachable_line
|
|
543
579
|
end # execute_command_gen4
|
|
544
580
|
|
|
545
581
|
# This is older API
|
|
@@ -549,7 +585,7 @@ module Aspera
|
|
|
549
585
|
async_name = options.get_option(:sync_name)
|
|
550
586
|
if async_name.nil?
|
|
551
587
|
async_id = instance_identifier
|
|
552
|
-
if async_id.eql?(
|
|
588
|
+
if async_id.eql?(ExtendedValue::ALL) && %i[show delete].include?(command)
|
|
553
589
|
async_ids = @api_node.read('async/list')[:data]['sync_ids']
|
|
554
590
|
else
|
|
555
591
|
Integer(async_id) # must be integer
|
|
@@ -572,7 +608,7 @@ module Aspera
|
|
|
572
608
|
when :show
|
|
573
609
|
resp = @api_node.create('async/summary', post_data)[:data]['sync_summaries']
|
|
574
610
|
return Main.result_empty if resp.empty?
|
|
575
|
-
return { type: :object_list, data: resp, fields: %w[snid name local_dir remote_dir] } if async_id.eql?(
|
|
611
|
+
return { type: :object_list, data: resp, fields: %w[snid name local_dir remote_dir] } if async_id.eql?(ExtendedValue::ALL)
|
|
576
612
|
return { type: :single_object, data: resp.first }
|
|
577
613
|
when :delete
|
|
578
614
|
resp = @api_node.create('async/delete', post_data)[:data]
|
|
@@ -589,7 +625,7 @@ module Aspera
|
|
|
589
625
|
# filename str
|
|
590
626
|
# skip int
|
|
591
627
|
# status int
|
|
592
|
-
filter =
|
|
628
|
+
filter = query_option
|
|
593
629
|
post_data.merge!(filter) unless filter.nil?
|
|
594
630
|
resp = @api_node.create('async/files', post_data)[:data]
|
|
595
631
|
data = resp['sync_files']
|
|
@@ -620,6 +656,20 @@ module Aspera
|
|
|
620
656
|
end
|
|
621
657
|
end
|
|
622
658
|
|
|
659
|
+
# @return [Integer] id of the sync
|
|
660
|
+
# @raise [Cli::BadArgument] if no such sync, or not by name
|
|
661
|
+
# @param [String] field name of the field to search
|
|
662
|
+
# @param [String] value value of the field to search
|
|
663
|
+
def ssync_lookup(field, value)
|
|
664
|
+
raise Cli::BadArgument, "Only search by name is supported (#{field})" unless field.eql?('name')
|
|
665
|
+
@api_node.read('asyncs')[:data]['ids'].each do |id|
|
|
666
|
+
sync_info = @api_node.read("asyncs/#{id}")[:data]['configuration']
|
|
667
|
+
# name is unique, so we can return
|
|
668
|
+
return id if sync_info[field].eql?(value)
|
|
669
|
+
end
|
|
670
|
+
raise Cli::BadArgument, "no such sync: #{field}=#{value}"
|
|
671
|
+
end
|
|
672
|
+
|
|
623
673
|
ACTIONS = %i[
|
|
624
674
|
async
|
|
625
675
|
ssync
|
|
@@ -629,7 +679,9 @@ module Aspera
|
|
|
629
679
|
watch_folder
|
|
630
680
|
central
|
|
631
681
|
asperabrowser
|
|
632
|
-
basic_token
|
|
682
|
+
basic_token
|
|
683
|
+
bearer_token
|
|
684
|
+
simulator].concat(COMMON_ACTIONS).freeze
|
|
633
685
|
|
|
634
686
|
def execute_action(command=nil, prefix_path=nil)
|
|
635
687
|
command ||= options.get_next_command(ACTIONS)
|
|
@@ -640,17 +692,15 @@ module Aspera
|
|
|
640
692
|
# newer API
|
|
641
693
|
sync_command = options.get_next_command(%i[start stop bandwidth counters files state summary].concat(Plugin::ALL_OPS) - %i[modify])
|
|
642
694
|
case sync_command
|
|
643
|
-
when *Plugin::ALL_OPS then return entity_command(sync_command, @api_node, 'asyncs', item_list_key: 'ids')
|
|
695
|
+
when *Plugin::ALL_OPS then return entity_command(sync_command, @api_node, 'asyncs', item_list_key: 'ids'){|field, value|ssync_lookup(field, value)}
|
|
644
696
|
else
|
|
645
|
-
asyncs_id = instance_identifier
|
|
697
|
+
asyncs_id = instance_identifier {|field, value|ssync_lookup(field, value)}
|
|
646
698
|
parameters = nil
|
|
647
699
|
if %i[start stop].include?(sync_command)
|
|
648
700
|
@api_node.create("asyncs/#{asyncs_id}/#{sync_command}", parameters)
|
|
649
701
|
return Main.result_status('Done')
|
|
650
702
|
end
|
|
651
|
-
if %i[bandwidth counters files].include?(sync_command)
|
|
652
|
-
parameters = value_or_query(allowed_types: Hash, mandatory: false) || {}
|
|
653
|
-
end
|
|
703
|
+
parameters = query_option(default: {}) if %i[bandwidth counters files].include?(sync_command)
|
|
654
704
|
return { type: :single_object, data: @api_node.read("asyncs/#{asyncs_id}/#{sync_command}", parameters)[:data] }
|
|
655
705
|
end
|
|
656
706
|
when :stream
|
|
@@ -660,13 +710,13 @@ module Aspera
|
|
|
660
710
|
resp = @api_node.read('ops/transfers', old_query_read_delete)
|
|
661
711
|
return { type: :object_list, data: resp[:data], fields: %w[id status] } # TODO: useful?
|
|
662
712
|
when :create
|
|
663
|
-
resp = @api_node.create('streams', value_create_modify(command: command
|
|
713
|
+
resp = @api_node.create('streams', value_create_modify(command: command))
|
|
664
714
|
return { type: :single_object, data: resp[:data] }
|
|
665
715
|
when :show
|
|
666
716
|
resp = @api_node.read("ops/transfers/#{options.get_next_argument('transfer id')}")
|
|
667
717
|
return { type: :other_struct, data: resp[:data] }
|
|
668
718
|
when :modify
|
|
669
|
-
resp = @api_node.update("streams/#{options.get_next_argument('transfer id')}", value_create_modify(command: command
|
|
719
|
+
resp = @api_node.update("streams/#{options.get_next_argument('transfer id')}", value_create_modify(command: command))
|
|
670
720
|
return { type: :other_struct, data: resp[:data] }
|
|
671
721
|
when :cancel
|
|
672
722
|
resp = @api_node.cancel("streams/#{options.get_next_argument('transfer id')}")
|
|
@@ -675,7 +725,7 @@ module Aspera
|
|
|
675
725
|
raise 'error'
|
|
676
726
|
end
|
|
677
727
|
when :transfer
|
|
678
|
-
command = options.get_next_command(%i[list cancel show modify bandwidth_average])
|
|
728
|
+
command = options.get_next_command(%i[list cancel show modify bandwidth_average sessions])
|
|
679
729
|
res_class_path = 'ops/transfers'
|
|
680
730
|
if %i[cancel show modify].include?(command)
|
|
681
731
|
one_res_id = instance_identifier
|
|
@@ -683,15 +733,24 @@ module Aspera
|
|
|
683
733
|
end
|
|
684
734
|
case command
|
|
685
735
|
when :list
|
|
686
|
-
|
|
687
|
-
query = query_read_delete
|
|
688
|
-
raise 'Query must be a Hash' unless query.nil? || query.is_a?(Hash)
|
|
689
|
-
transfers_data = @api_node.read(res_class_path, query)[:data]
|
|
736
|
+
transfers_data = @api_node.read(res_class_path, query_read_delete)[:data]
|
|
690
737
|
return {
|
|
691
738
|
type: :object_list,
|
|
692
739
|
data: transfers_data,
|
|
693
740
|
fields: %w[id status start_spec.direction start_spec.remote_user start_spec.remote_host start_spec.destination_path]
|
|
694
741
|
}
|
|
742
|
+
when :sessions
|
|
743
|
+
transfers_data = @api_node.read(res_class_path, query_read_delete)[:data]
|
|
744
|
+
sessions = transfers_data.map{|t|t['sessions']}.flatten
|
|
745
|
+
sessions.each do |session|
|
|
746
|
+
session['start_time'] = Time.at(session['start_time_usec'] / 1_000_000.0).utc.iso8601(0)
|
|
747
|
+
session['end_time'] = Time.at(session['end_time_usec'] / 1_000_000.0).utc.iso8601(0)
|
|
748
|
+
end
|
|
749
|
+
return {
|
|
750
|
+
type: :object_list,
|
|
751
|
+
data: sessions,
|
|
752
|
+
fields: %w[id status start_time end_time target_rate_kbps]
|
|
753
|
+
}
|
|
695
754
|
when :cancel
|
|
696
755
|
resp = @api_node.cancel(one_res_path)
|
|
697
756
|
return { type: :other_struct, data: resp[:data] }
|
|
@@ -702,7 +761,7 @@ module Aspera
|
|
|
702
761
|
resp = @api_node.update(one_res_path, options.get_next_argument('update value', type: Hash))
|
|
703
762
|
return { type: :other_struct, data: resp[:data] }
|
|
704
763
|
when :bandwidth_average
|
|
705
|
-
transfers_data = @api_node.read(res_class_path,
|
|
764
|
+
transfers_data = @api_node.read(res_class_path, query_read_delete)[:data]
|
|
706
765
|
# collect all key dates
|
|
707
766
|
bandwidth_period = {}
|
|
708
767
|
dir_info = %i[avg_kbps sessions].freeze
|
|
@@ -779,7 +838,7 @@ module Aspera
|
|
|
779
838
|
@api_node.params[:headers]['X-aspera-WF-version'] = '2017_10_23'
|
|
780
839
|
case command
|
|
781
840
|
when :create
|
|
782
|
-
resp = @api_node.create(res_class_path, value_create_modify(command: command
|
|
841
|
+
resp = @api_node.create(res_class_path, value_create_modify(command: command))
|
|
783
842
|
return Main.result_status("#{resp[:data]['id']} created")
|
|
784
843
|
when :list
|
|
785
844
|
resp = @api_node.read(res_class_path, old_query_read_delete)
|
|
@@ -787,7 +846,7 @@ module Aspera
|
|
|
787
846
|
when :show
|
|
788
847
|
return { type: :single_object, data: @api_node.read(one_res_path)[:data]}
|
|
789
848
|
when :modify
|
|
790
|
-
@api_node.update(one_res_path,
|
|
849
|
+
@api_node.update(one_res_path, query_option(mandatory: true))
|
|
791
850
|
return Main.result_status("#{one_res_id} updated")
|
|
792
851
|
when :delete
|
|
793
852
|
@api_node.delete(one_res_path)
|
|
@@ -799,7 +858,7 @@ module Aspera
|
|
|
799
858
|
command = options.get_next_command(%i[session file])
|
|
800
859
|
validator_id = options.get_option(:validator)
|
|
801
860
|
validation = {'validator_id' => validator_id} unless validator_id.nil?
|
|
802
|
-
request_data =
|
|
861
|
+
request_data = query_option(default: {})
|
|
803
862
|
case command
|
|
804
863
|
when :session
|
|
805
864
|
command = options.get_next_command([:list])
|
|
@@ -820,7 +879,7 @@ module Aspera
|
|
|
820
879
|
request_data.deep_merge!({'validation' => validation}) unless validation.nil?
|
|
821
880
|
resp = @api_node.create('services/rest/transfers/v1/files', request_data)[:data]
|
|
822
881
|
resp = JSON.parse(resp) if resp.is_a?(String)
|
|
823
|
-
Log.dump(:resp, resp)
|
|
882
|
+
Log.log.debug{Log.dump(:resp, resp)}
|
|
824
883
|
return { type: :object_list, data: resp['file_transfer_info_result']['file_transfer_info'], fields: %w[session_uuid file_id status path]}
|
|
825
884
|
when :modify
|
|
826
885
|
request_data.deep_merge!(validation) unless validation.nil?
|
|
@@ -839,7 +898,27 @@ module Aspera
|
|
|
839
898
|
OpenApplication.instance.uri(options.get_option(:asperabrowserurl) + '?goto=' + encoded_params)
|
|
840
899
|
return Main.result_status('done')
|
|
841
900
|
when :basic_token
|
|
842
|
-
return Main.result_status(Rest.
|
|
901
|
+
return Main.result_status(Rest.basic_token(options.get_option(:username, mandatory: true), options.get_option(:password, mandatory: true)))
|
|
902
|
+
when :bearer_token
|
|
903
|
+
private_key = OpenSSL::PKey::RSA.new(options.get_next_argument('private RSA key PEM value', type: String))
|
|
904
|
+
token_info = options.get_next_argument('user and group identification', type: Hash)
|
|
905
|
+
access_key = options.get_option(:username, mandatory: true)
|
|
906
|
+
return Main.result_status(Aspera::Node.bearer_token(payload: token_info, access_key: access_key, private_key: private_key))
|
|
907
|
+
when :simulator
|
|
908
|
+
require 'aspera/node_simulator'
|
|
909
|
+
parameters = value_create_modify(command: command)
|
|
910
|
+
parameters = parameters.symbolize_keys
|
|
911
|
+
raise 'Missing key: url' unless parameters.key?(:url)
|
|
912
|
+
uri = URI.parse(parameters[:url])
|
|
913
|
+
server = WebServerSimple.new(uri, certificate: parameters[:certificate])
|
|
914
|
+
server.mount(uri.path, NodeSimulatorServlet, parameters[:credentials], transfer)
|
|
915
|
+
# on ctrl-c, tell server main loop to exit
|
|
916
|
+
trap('INT') { server.shutdown }
|
|
917
|
+
formatter.display_status("Node Simulator listening on #{uri.port}")
|
|
918
|
+
Log.log.info{"Listening on #{uri.port}"}
|
|
919
|
+
# this is blocking until server exits
|
|
920
|
+
server.start
|
|
921
|
+
return Main.result_status('Simulator terminated')
|
|
843
922
|
end # case command
|
|
844
923
|
raise 'ERROR: shall not reach this line'
|
|
845
924
|
end # execute_action
|