aspera-cli 4.17.0 → 4.18.1
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 +3 -4
- data/CHANGELOG.md +33 -0
- data/CONTRIBUTING.md +15 -1
- data/README.md +711 -432
- data/bin/ascli +5 -0
- data/bin/asession +2 -2
- data/examples/build_package.sh +28 -0
- data/lib/aspera/agent/alpha.rb +10 -8
- data/lib/aspera/agent/base.rb +9 -6
- data/lib/aspera/agent/connect.rb +7 -8
- data/lib/aspera/agent/direct.rb +56 -37
- data/lib/aspera/agent/httpgw.rb +23 -324
- data/lib/aspera/agent/node.rb +19 -20
- data/lib/aspera/agent/trsdk.rb +19 -20
- data/lib/aspera/api/aoc.rb +17 -14
- data/lib/aspera/api/cos_node.rb +4 -4
- data/lib/aspera/api/httpgw.rb +342 -0
- data/lib/aspera/api/node.rb +135 -89
- data/lib/aspera/ascmd.rb +4 -3
- data/lib/aspera/ascp/installation.rb +15 -7
- data/lib/aspera/ascp/management.rb +2 -2
- data/lib/aspera/ascp/products.rb +1 -1
- data/lib/aspera/cli/basic_auth_plugin.rb +5 -9
- data/lib/aspera/cli/extended_value.rb +35 -16
- data/lib/aspera/cli/formatter.rb +161 -70
- data/lib/aspera/cli/hints.rb +18 -0
- data/lib/aspera/cli/main.rb +32 -39
- data/lib/aspera/cli/manager.rb +151 -119
- data/lib/aspera/cli/plugin.rb +27 -21
- data/lib/aspera/cli/plugin_factory.rb +31 -20
- data/lib/aspera/cli/plugins/alee.rb +14 -2
- data/lib/aspera/cli/plugins/aoc.rb +152 -141
- data/lib/aspera/cli/plugins/ats.rb +1 -1
- data/lib/aspera/cli/plugins/config.rb +72 -65
- data/lib/aspera/cli/plugins/console.rb +8 -5
- data/lib/aspera/cli/plugins/faspex.rb +32 -23
- data/lib/aspera/cli/plugins/faspex5.rb +232 -156
- data/lib/aspera/cli/plugins/faspio.rb +85 -0
- data/lib/aspera/cli/plugins/httpgw.rb +55 -0
- data/lib/aspera/cli/plugins/node.rb +129 -64
- data/lib/aspera/cli/plugins/orchestrator.rb +33 -30
- data/lib/aspera/cli/plugins/preview.rb +7 -3
- data/lib/aspera/cli/plugins/server.rb +6 -6
- data/lib/aspera/cli/plugins/shares.rb +16 -14
- data/lib/aspera/cli/special_values.rb +13 -0
- data/lib/aspera/cli/sync_actions.rb +10 -10
- data/lib/aspera/cli/transfer_agent.rb +7 -6
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/environment.rb +70 -9
- data/lib/aspera/faspex_gw.rb +5 -4
- data/lib/aspera/faspex_postproc.rb +2 -2
- data/lib/aspera/log.rb +6 -3
- data/lib/aspera/node_simulator.rb +2 -2
- data/lib/aspera/oauth/base.rb +31 -19
- data/lib/aspera/oauth/factory.rb +12 -13
- data/lib/aspera/oauth/generic.rb +1 -0
- data/lib/aspera/oauth/jwt.rb +18 -15
- data/lib/aspera/oauth/url_json.rb +8 -6
- data/lib/aspera/oauth/web.rb +2 -2
- data/lib/aspera/persistency_folder.rb +2 -2
- data/lib/aspera/preview/generator.rb +3 -3
- data/lib/aspera/preview/options.rb +3 -3
- data/lib/aspera/preview/terminal.rb +4 -4
- data/lib/aspera/preview/utils.rb +3 -3
- data/lib/aspera/proxy_auto_config.rb +5 -1
- data/lib/aspera/rest.rb +105 -88
- data/lib/aspera/rest_call_error.rb +1 -1
- data/lib/aspera/rest_error_analyzer.rb +2 -2
- data/lib/aspera/rest_errors_aspera.rb +1 -1
- data/lib/aspera/resumer.rb +1 -1
- data/lib/aspera/secret_hider.rb +2 -4
- data/lib/aspera/ssh.rb +1 -1
- data/lib/aspera/transfer/parameters.rb +39 -36
- data/lib/aspera/transfer/spec.rb +2 -0
- data/lib/aspera/transfer/sync.rb +2 -1
- data/lib/aspera/transfer/uri.rb +1 -1
- data/lib/aspera/uri_reader.rb +5 -4
- data/lib/aspera/web_auth.rb +1 -1
- data/lib/aspera/web_server_simple.rb +4 -3
- data.tar.gz.sig +0 -0
- metadata +7 -4
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/plugins/bss.rb +0 -71
- data/lib/aspera/open_application.rb +0 -71
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'aspera/rest'
|
|
4
|
+
require 'aspera/api/httpgw'
|
|
5
|
+
require 'aspera/nagios'
|
|
6
|
+
|
|
7
|
+
module Aspera
|
|
8
|
+
module Cli
|
|
9
|
+
module Plugins
|
|
10
|
+
class Httpgw < Plugin
|
|
11
|
+
class << self
|
|
12
|
+
def application_name
|
|
13
|
+
'HTTP Gateway'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def detect(base_url)
|
|
17
|
+
api = Api::Httpgw.new(url: base_url)
|
|
18
|
+
api_info = api.info
|
|
19
|
+
return {
|
|
20
|
+
url: base_url,
|
|
21
|
+
version: api_info['version']
|
|
22
|
+
} if api_info.is_a?(Hash) && api_info.key?('download_endpoint')
|
|
23
|
+
return nil
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
ACTIONS = %i[health info].freeze
|
|
27
|
+
|
|
28
|
+
def initialize(**env)
|
|
29
|
+
super
|
|
30
|
+
options.declare(:url, 'URL of application, e.g. https://app.example.com/aspera/app')
|
|
31
|
+
options.parse_options!
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def execute_action
|
|
35
|
+
base_url = options.get_option(:url, mandatory: true)
|
|
36
|
+
command = options.get_next_command(ACTIONS)
|
|
37
|
+
case command
|
|
38
|
+
when :health
|
|
39
|
+
nagios = Nagios.new
|
|
40
|
+
begin
|
|
41
|
+
Api::Httpgw.new(url: base_url)
|
|
42
|
+
nagios.add_ok('api', 'answered ok')
|
|
43
|
+
rescue StandardError => e
|
|
44
|
+
nagios.add_critical('api', e.to_s)
|
|
45
|
+
end
|
|
46
|
+
return nagios.result
|
|
47
|
+
when :info
|
|
48
|
+
api_v1 = Api::Httpgw.new(url: base_url)
|
|
49
|
+
return {type: :single_object, data: api_v1.info}
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# cspell:ignore snid fnid bidi ssync asyncs rund asnodeadmin mkfile mklink asperabrowser asperabrowserurl watchfolders watchfolderd entsrv
|
|
4
4
|
require 'aspera/cli/basic_auth_plugin'
|
|
5
5
|
require 'aspera/cli/sync_actions'
|
|
6
|
+
require 'aspera/cli/special_values'
|
|
6
7
|
require 'aspera/transfer/spec'
|
|
7
8
|
require 'aspera/nagios'
|
|
8
9
|
require 'aspera/hash_ext'
|
|
@@ -44,7 +45,8 @@ module Aspera
|
|
|
44
45
|
next unless result[:http].body.eql?('')
|
|
45
46
|
url_length = -2 - test_endpoint.length
|
|
46
47
|
return {
|
|
47
|
-
url:
|
|
48
|
+
url: result[:http].uri.to_s[0..url_length],
|
|
49
|
+
version: 'requires authentication'
|
|
48
50
|
}
|
|
49
51
|
rescue StandardError => e
|
|
50
52
|
error = e
|
|
@@ -92,7 +94,7 @@ module Aspera
|
|
|
92
94
|
SEARCH_REMOVE_FIELDS = %w[basename permissions].freeze
|
|
93
95
|
|
|
94
96
|
# actions in execute_command_gen3
|
|
95
|
-
COMMANDS_GEN3 = %i[search space mkdir mklink mkfile rename delete browse upload download http_node_download sync]
|
|
97
|
+
COMMANDS_GEN3 = %i[search space mkdir mklink mkfile rename delete browse upload download http_node_download sync transport]
|
|
96
98
|
|
|
97
99
|
BASE_ACTIONS = %i[api_details].concat(COMMANDS_GEN3).freeze
|
|
98
100
|
|
|
@@ -161,7 +163,7 @@ module Aspera
|
|
|
161
163
|
# translates paths results into CLI result, and removes prefix
|
|
162
164
|
def c_result_translate_rem_prefix(response, type, success_msg, path_prefix)
|
|
163
165
|
errors = []
|
|
164
|
-
final_result = { data: [],
|
|
166
|
+
final_result = {type: :object_list, data: [], fields: [type, 'result']}
|
|
165
167
|
JSON.parse(response[:http].body)['paths'].each do |p|
|
|
166
168
|
result = success_msg
|
|
167
169
|
if p.key?('error')
|
|
@@ -178,24 +180,78 @@ module Aspera
|
|
|
178
180
|
return c_result_remove_prefix_path(final_result, type, path_prefix)
|
|
179
181
|
end
|
|
180
182
|
|
|
181
|
-
#
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
183
|
+
# directory: node, container: shares
|
|
184
|
+
FOLDER_TYPE = %w[directory container].freeze
|
|
185
|
+
|
|
186
|
+
def browse_gen3(prefix_path)
|
|
187
|
+
folders_to_process = [get_one_argument_with_prefix(prefix_path, 'path')]
|
|
188
|
+
query = options.get_option(:query, default: {})
|
|
189
|
+
# special parameter: max number of entries in result
|
|
190
|
+
max_items = query.delete('max')
|
|
191
|
+
# special parameter: recursive browsing
|
|
192
|
+
recursive = query.delete('recursive')
|
|
193
|
+
# special parameter: only return one entry for the path, even if folder
|
|
194
|
+
only_path = query.delete('self')
|
|
195
|
+
# allow user to specify a single call, and not recursive
|
|
196
|
+
single_call = query.key?('skip')
|
|
197
|
+
# API default is 100, so use 1000 for default
|
|
198
|
+
query['count'] ||= 1000
|
|
199
|
+
raise Cli::BadArgument, 'options recursive and skip cannot be used together' if recursive && single_call
|
|
200
|
+
all_items = []
|
|
201
|
+
until folders_to_process.empty?
|
|
202
|
+
path = folders_to_process.shift
|
|
203
|
+
query['path'] = path
|
|
204
|
+
offset = 0
|
|
205
|
+
total_count = nil
|
|
206
|
+
result = nil
|
|
207
|
+
loop do
|
|
208
|
+
# example: send_result={'items'=>[{'file'=>"filename1","permissions"=>[{'name'=>'read'},{'name'=>'write'}]}]}
|
|
209
|
+
response = @api_node.call(
|
|
210
|
+
operation: 'POST',
|
|
211
|
+
subpath: 'files/browse',
|
|
212
|
+
headers: {'Accept' => 'application/json'},
|
|
213
|
+
body: query,
|
|
214
|
+
body_type: :json)
|
|
215
|
+
# 'file','symbolic_link'
|
|
216
|
+
if only_path || !FOLDER_TYPE.include?(response[:data]['self']['type'])
|
|
217
|
+
result = { type: :single_object, data: response[:data]['self']}
|
|
218
|
+
break
|
|
219
|
+
end
|
|
220
|
+
items = response[:data]['items']
|
|
221
|
+
total_count ||= response[:data]['total_count']
|
|
222
|
+
all_items.concat(items)
|
|
223
|
+
if single_call
|
|
224
|
+
formatter.display_item_count(response[:data]['item_count'], total_count)
|
|
225
|
+
break
|
|
226
|
+
end
|
|
227
|
+
if recursive
|
|
228
|
+
folders_to_process.concat(items.select{|i|FOLDER_TYPE.include?(i['type'])}.map{|i|i['path']})
|
|
229
|
+
end
|
|
230
|
+
if !max_items.nil? && (all_items.count >= max_items)
|
|
231
|
+
all_items = all_items.slice(0, max_items) if all_items.count > max_items
|
|
232
|
+
break
|
|
233
|
+
end
|
|
234
|
+
break if all_items.count >= total_count
|
|
235
|
+
offset += items.count
|
|
236
|
+
query['skip'] = offset
|
|
237
|
+
formatter.long_operation_running(all_items.count)
|
|
238
|
+
end
|
|
239
|
+
query.delete('skip')
|
|
240
|
+
end
|
|
241
|
+
result ||= {type: :object_list, data: all_items}
|
|
242
|
+
return c_result_remove_prefix_path(result, 'path', prefix_path)
|
|
188
243
|
end
|
|
189
244
|
|
|
190
245
|
# file and folder related commands
|
|
191
246
|
def execute_command_gen3(command, prefix_path)
|
|
192
247
|
case command
|
|
193
248
|
when :delete
|
|
194
|
-
|
|
249
|
+
# TODO: add query for recursive
|
|
250
|
+
paths_to_delete = get_all_arguments_with_prefix(prefix_path, 'file list')
|
|
195
251
|
resp = @api_node.create('files/delete', { paths: paths_to_delete.map{|i| {'path' => i.start_with?('/') ? i : "/#{i}"} }})
|
|
196
252
|
return c_result_translate_rem_prefix(resp, 'file', 'deleted', prefix_path)
|
|
197
253
|
when :search
|
|
198
|
-
search_root =
|
|
254
|
+
search_root = get_one_argument_with_prefix(prefix_path, 'search root')
|
|
199
255
|
parameters = {'path' => search_root}
|
|
200
256
|
other_options = query_option
|
|
201
257
|
parameters.merge!(other_options) unless other_options.nil?
|
|
@@ -207,48 +263,34 @@ module Aspera
|
|
|
207
263
|
formatter.display_status("params: #{resp[:data]['parameters'].keys.map{|k|"#{k}:#{resp[:data]['parameters'][k]}"}.join(',')}")
|
|
208
264
|
return c_result_remove_prefix_path(result, 'path', prefix_path)
|
|
209
265
|
when :space
|
|
210
|
-
path_list =
|
|
211
|
-
path_list = [path_list] unless path_list.is_a?(Array)
|
|
266
|
+
path_list = get_all_arguments_with_prefix(prefix_path, 'folder path or ext.val. list')
|
|
212
267
|
resp = @api_node.create('space', { 'paths' => path_list.map {|i| { path: i} } })
|
|
213
|
-
result = { data: resp[:data]['paths']
|
|
268
|
+
result = { type: :object_list, data: resp[:data]['paths']}
|
|
214
269
|
# return c_result_translate_rem_prefix(resp,'folder','created',prefix_path)
|
|
215
270
|
return c_result_remove_prefix_path(result, 'path', prefix_path)
|
|
216
271
|
when :mkdir
|
|
217
|
-
path_list =
|
|
218
|
-
|
|
219
|
-
resp = @api_node.create('files/create', { 'paths' => [{ type: :directory, path: path_list }] })
|
|
272
|
+
path_list = get_all_arguments_with_prefix(prefix_path, 'folder path or ext.val. list')
|
|
273
|
+
resp = @api_node.create('files/create', { 'paths' => path_list.map{|i|{ type: :directory, path: i }}})
|
|
220
274
|
return c_result_translate_rem_prefix(resp, 'folder', 'created', prefix_path)
|
|
221
275
|
when :mklink
|
|
222
|
-
target =
|
|
223
|
-
|
|
224
|
-
resp = @api_node.create('files/create', { 'paths' => [{ type: :symbolic_link, path:
|
|
276
|
+
target = get_one_argument_with_prefix(prefix_path, 'target')
|
|
277
|
+
one_path = get_one_argument_with_prefix(prefix_path, 'link path')
|
|
278
|
+
resp = @api_node.create('files/create', { 'paths' => [{ type: :symbolic_link, path: one_path, target: { path: target} }] })
|
|
225
279
|
return c_result_translate_rem_prefix(resp, 'folder', 'created', prefix_path)
|
|
226
280
|
when :mkfile
|
|
227
|
-
|
|
281
|
+
one_path = get_one_argument_with_prefix(prefix_path, 'file path')
|
|
228
282
|
contents64 = Base64.strict_encode64(options.get_next_argument('contents'))
|
|
229
|
-
resp = @api_node.create('files/create', { 'paths' => [{ type: :file, path:
|
|
283
|
+
resp = @api_node.create('files/create', { 'paths' => [{ type: :file, path: one_path, contents: contents64 }] })
|
|
230
284
|
return c_result_translate_rem_prefix(resp, 'folder', 'created', prefix_path)
|
|
231
285
|
when :rename
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
286
|
+
# TODO: multiple ?
|
|
287
|
+
path_base = get_one_argument_with_prefix(prefix_path, 'path_base')
|
|
288
|
+
path_src = get_one_argument_with_prefix(prefix_path, 'path_src')
|
|
289
|
+
path_dst = get_one_argument_with_prefix(prefix_path, 'path_dst')
|
|
235
290
|
resp = @api_node.create('files/rename', { 'paths' => [{ 'path' => path_base, 'source' => path_src, 'destination' => path_dst }] })
|
|
236
291
|
return c_result_translate_rem_prefix(resp, 'entry', 'moved', prefix_path)
|
|
237
292
|
when :browse
|
|
238
|
-
|
|
239
|
-
additional_query = options.get_option(:query)
|
|
240
|
-
query.merge!(additional_query) unless additional_query.nil?
|
|
241
|
-
send_result = @api_node.create('files/browse', query)[:data]
|
|
242
|
-
# example: send_result={'items'=>[{'file'=>"filename1","permissions"=>[{'name'=>'read'},{'name'=>'write'}]}]}
|
|
243
|
-
# if there is no items
|
|
244
|
-
case send_result['self']['type']
|
|
245
|
-
when 'directory', 'container' # directory: node, container: shares
|
|
246
|
-
result = { data: send_result['items'], type: :object_list }
|
|
247
|
-
formatter.display_item_count(send_result['item_count'], send_result['total_count'])
|
|
248
|
-
else # 'file','symbolic_link'
|
|
249
|
-
result = { data: send_result['self'], type: :single_object}
|
|
250
|
-
end
|
|
251
|
-
return c_result_remove_prefix_path(result, 'path', prefix_path)
|
|
293
|
+
return browse_gen3(prefix_path)
|
|
252
294
|
when :sync
|
|
253
295
|
return execute_sync_action do |sync_direction, local_path, remote_path|
|
|
254
296
|
# Gen3 API
|
|
@@ -296,13 +338,15 @@ module Aspera
|
|
|
296
338
|
transfer_spec.delete('paths') if command.eql?(:upload)
|
|
297
339
|
return Main.result_transfer(transfer.start(transfer_spec))
|
|
298
340
|
when :http_node_download
|
|
299
|
-
remote_path =
|
|
341
|
+
remote_path = get_one_argument_with_prefix(prefix_path, 'remote path')
|
|
300
342
|
file_name = File.basename(remote_path)
|
|
301
343
|
@api_node.call(
|
|
302
344
|
operation: 'GET',
|
|
303
345
|
subpath: "files/#{URI.encode_www_form_component(remote_path)}/contents",
|
|
304
346
|
save_to_file: File.join(transfer.destination_folder(Transfer::Spec::DIRECTION_RECEIVE), file_name))
|
|
305
347
|
return Main.result_status("downloaded: #{file_name}")
|
|
348
|
+
when :transport
|
|
349
|
+
return {type: :single_object, data: @api_node.transport_params}
|
|
306
350
|
end
|
|
307
351
|
Aspera.error_unreachable_line
|
|
308
352
|
end
|
|
@@ -338,7 +382,7 @@ module Aspera
|
|
|
338
382
|
when :set_bearer_key
|
|
339
383
|
access_key_id = options.get_next_argument('access key id')
|
|
340
384
|
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',
|
|
385
|
+
bearer_key_pem = options.get_next_argument('public or private RSA key PEM value', validation: String)
|
|
342
386
|
key = OpenSSL::PKey.read(bearer_key_pem)
|
|
343
387
|
key = key.public_key if key.private?
|
|
344
388
|
bearer_key_pem = key.to_pem
|
|
@@ -358,9 +402,10 @@ module Aspera
|
|
|
358
402
|
begin
|
|
359
403
|
@api_node.call(
|
|
360
404
|
operation: 'POST',
|
|
361
|
-
subpath:
|
|
362
|
-
headers:
|
|
363
|
-
|
|
405
|
+
subpath: 'services/soap/Transfer-201210',
|
|
406
|
+
headers: {'Content-Type' => 'text/xml;charset=UTF-8', 'SOAPAction' => 'FASPSessionNET-200911#GetSessionInfo'},
|
|
407
|
+
body: CENTRAL_SOAP_API_TEST,
|
|
408
|
+
body_type: :text)[:http].body
|
|
364
409
|
nagios.add_ok('central', 'accessible by node')
|
|
365
410
|
rescue StandardError => e
|
|
366
411
|
nagios.add_critical('central', e.to_s)
|
|
@@ -420,7 +465,7 @@ module Aspera
|
|
|
420
465
|
result[:password] = apifid[:api].auth_params[:password]
|
|
421
466
|
when :oauth2
|
|
422
467
|
result[:username] = apifid[:api].params[:headers][Api::Node::HEADER_X_ASPERA_ACCESS_KEY]
|
|
423
|
-
result[:password] = apifid[:api].
|
|
468
|
+
result[:password] = apifid[:api].oauth.token
|
|
424
469
|
else Aspera.error_unreachable_line
|
|
425
470
|
end
|
|
426
471
|
return {type: :single_object, data: result} if command_repo.eql?(:node_info)
|
|
@@ -431,7 +476,7 @@ module Aspera
|
|
|
431
476
|
apifid = @api_node.resolve_api_fid(top_file_id, options.get_next_argument('path'))
|
|
432
477
|
file_info = apifid[:api].read("files/#{apifid[:file_id]}")[:data]
|
|
433
478
|
if file_info['type'].eql?('folder')
|
|
434
|
-
result = apifid[:api].read("files/#{apifid[:file_id]}/files",
|
|
479
|
+
result = apifid[:api].read("files/#{apifid[:file_id]}/files", query_read_delete)
|
|
435
480
|
items = result[:data]
|
|
436
481
|
formatter.display_item_count(result[:data].length, result[:http]['X-Total-Count'])
|
|
437
482
|
else
|
|
@@ -528,7 +573,7 @@ module Aspera
|
|
|
528
573
|
return {type: :single_object, data: items}
|
|
529
574
|
when :modify
|
|
530
575
|
apifid = apifid_from_next_arg(top_file_id)
|
|
531
|
-
update_param = options.get_next_argument('update data',
|
|
576
|
+
update_param = options.get_next_argument('update data', validation: Hash)
|
|
532
577
|
apifid[:api].update("files/#{apifid[:file_id]}", update_param)[:data]
|
|
533
578
|
return Main.result_status('Done')
|
|
534
579
|
when :thumbnail
|
|
@@ -538,7 +583,7 @@ module Aspera
|
|
|
538
583
|
subpath: "files/#{apifid[:file_id]}/preview",
|
|
539
584
|
headers: {'Accept' => 'image/png'}
|
|
540
585
|
)
|
|
541
|
-
return Main.
|
|
586
|
+
return Main.result_image(result[:http].body, formatter: formatter)
|
|
542
587
|
when :permission
|
|
543
588
|
apifid = apifid_from_next_arg(top_file_id)
|
|
544
589
|
command_perm = options.get_next_command(%i[list create delete])
|
|
@@ -559,7 +604,7 @@ module Aspera
|
|
|
559
604
|
{'id' => one_id}
|
|
560
605
|
end
|
|
561
606
|
when :create
|
|
562
|
-
create_param = options.get_next_argument('creation data',
|
|
607
|
+
create_param = options.get_next_argument('creation data', validation: Hash)
|
|
563
608
|
raise 'no file_id' if create_param.key?('file_id')
|
|
564
609
|
create_param['file_id'] = apifid[:file_id]
|
|
565
610
|
create_param['access_levels'] = Api::Node::ACCESS_LEVELS unless create_param.key?('access_levels')
|
|
@@ -574,9 +619,9 @@ module Aspera
|
|
|
574
619
|
else Aspera.error_unreachable_line
|
|
575
620
|
end
|
|
576
621
|
else Aspera.error_unreachable_line
|
|
577
|
-
end
|
|
622
|
+
end
|
|
578
623
|
Aspera.error_unreachable_line
|
|
579
|
-
end
|
|
624
|
+
end
|
|
580
625
|
|
|
581
626
|
# This is older API
|
|
582
627
|
def execute_async
|
|
@@ -585,7 +630,7 @@ module Aspera
|
|
|
585
630
|
async_name = options.get_option(:sync_name)
|
|
586
631
|
if async_name.nil?
|
|
587
632
|
async_id = instance_identifier
|
|
588
|
-
if async_id.eql?(
|
|
633
|
+
if async_id.eql?(SpecialValues::ALL) && %i[show delete].include?(command)
|
|
589
634
|
async_ids = @api_node.read('async/list')[:data]['sync_ids']
|
|
590
635
|
else
|
|
591
636
|
Integer(async_id) # must be integer
|
|
@@ -608,7 +653,7 @@ module Aspera
|
|
|
608
653
|
when :show
|
|
609
654
|
resp = @api_node.create('async/summary', post_data)[:data]['sync_summaries']
|
|
610
655
|
return Main.result_empty if resp.empty?
|
|
611
|
-
return { type: :object_list, data: resp, fields: %w[snid name local_dir remote_dir] } if async_id.eql?(
|
|
656
|
+
return { type: :object_list, data: resp, fields: %w[snid name local_dir remote_dir] } if async_id.eql?(SpecialValues::ALL)
|
|
612
657
|
return { type: :single_object, data: resp.first }
|
|
613
658
|
when :delete
|
|
614
659
|
resp = @api_node.create('async/delete', post_data)[:data]
|
|
@@ -695,11 +740,15 @@ module Aspera
|
|
|
695
740
|
when *Plugin::ALL_OPS then return entity_command(sync_command, @api_node, 'asyncs', item_list_key: 'ids'){|field, value|ssync_lookup(field, value)}
|
|
696
741
|
else
|
|
697
742
|
asyncs_id = instance_identifier {|field, value|ssync_lookup(field, value)}
|
|
698
|
-
parameters = nil
|
|
699
743
|
if %i[start stop].include?(sync_command)
|
|
700
|
-
@api_node.
|
|
744
|
+
@api_node.call(
|
|
745
|
+
operation: 'POST',
|
|
746
|
+
subpath: "asyncs/#{asyncs_id}/#{sync_command}",
|
|
747
|
+
body: '',
|
|
748
|
+
body_type: :text)[:http].body
|
|
701
749
|
return Main.result_status('Done')
|
|
702
750
|
end
|
|
751
|
+
parameters = nil
|
|
703
752
|
parameters = query_option(default: {}) if %i[bandwidth counters files].include?(sync_command)
|
|
704
753
|
return { type: :single_object, data: @api_node.read("asyncs/#{asyncs_id}/#{sync_command}", parameters)[:data] }
|
|
705
754
|
end
|
|
@@ -707,7 +756,7 @@ module Aspera
|
|
|
707
756
|
command = options.get_next_command(%i[list create show modify cancel])
|
|
708
757
|
case command
|
|
709
758
|
when :list
|
|
710
|
-
resp = @api_node.read('ops/transfers',
|
|
759
|
+
resp = @api_node.read('ops/transfers', query_read_delete)
|
|
711
760
|
return { type: :object_list, data: resp[:data], fields: %w[id status] } # TODO: useful?
|
|
712
761
|
when :create
|
|
713
762
|
resp = @api_node.create('streams', value_create_modify(command: command))
|
|
@@ -758,7 +807,7 @@ module Aspera
|
|
|
758
807
|
resp = @api_node.read(one_res_path)
|
|
759
808
|
return { type: :other_struct, data: resp[:data] }
|
|
760
809
|
when :modify
|
|
761
|
-
resp = @api_node.update(one_res_path, options.get_next_argument('update value',
|
|
810
|
+
resp = @api_node.update(one_res_path, options.get_next_argument('update value', validation: Hash))
|
|
762
811
|
return { type: :other_struct, data: resp[:data] }
|
|
763
812
|
when :bandwidth_average
|
|
764
813
|
transfers_data = @api_node.read(res_class_path, query_read_delete)[:data]
|
|
@@ -819,7 +868,7 @@ module Aspera
|
|
|
819
868
|
return { type: :object_list, data: resp[:data]['services'] }
|
|
820
869
|
when :create
|
|
821
870
|
# @json:'{"type":"WATCHFOLDERD","run_as":{"user":"user1"}}'
|
|
822
|
-
params = options.get_next_argument('
|
|
871
|
+
params = options.get_next_argument('creation data', validation: Hash)
|
|
823
872
|
resp = @api_node.create('rund/services', params)
|
|
824
873
|
return Main.result_status("#{resp[:data]['id']} created")
|
|
825
874
|
when :delete
|
|
@@ -841,7 +890,7 @@ module Aspera
|
|
|
841
890
|
resp = @api_node.create(res_class_path, value_create_modify(command: command))
|
|
842
891
|
return Main.result_status("#{resp[:data]['id']} created")
|
|
843
892
|
when :list
|
|
844
|
-
resp = @api_node.read(res_class_path,
|
|
893
|
+
resp = @api_node.read(res_class_path, query_read_delete)
|
|
845
894
|
return { type: :value_list, data: resp[:data]['ids'], name: 'id' }
|
|
846
895
|
when :show
|
|
847
896
|
return { type: :single_object, data: @api_node.read(one_res_path)[:data]}
|
|
@@ -895,13 +944,13 @@ module Aspera
|
|
|
895
944
|
}
|
|
896
945
|
# encode parameters so that it looks good in url
|
|
897
946
|
encoded_params = Base64.strict_encode64(Zlib::Deflate.deflate(JSON.generate(browse_params))).gsub(/=+$/, '').tr('+/', '-_').reverse
|
|
898
|
-
|
|
947
|
+
Environment.instance.open_uri("#{options.get_option(:asperabrowserurl)}?goto=#{encoded_params}")
|
|
899
948
|
return Main.result_status('done')
|
|
900
949
|
when :basic_token
|
|
901
950
|
return Main.result_status(Rest.basic_token(options.get_option(:username, mandatory: true), options.get_option(:password, mandatory: true)))
|
|
902
951
|
when :bearer_token
|
|
903
|
-
private_key = OpenSSL::PKey::RSA.new(options.get_next_argument('private RSA key PEM value',
|
|
904
|
-
token_info = options.get_next_argument('user and group identification',
|
|
952
|
+
private_key = OpenSSL::PKey::RSA.new(options.get_next_argument('private RSA key PEM value', validation: String))
|
|
953
|
+
token_info = options.get_next_argument('user and group identification', validation: Hash)
|
|
905
954
|
access_key = options.get_option(:username, mandatory: true)
|
|
906
955
|
return Main.result_status(Api::Node.bearer_token(payload: token_info, access_key: access_key, private_key: private_key))
|
|
907
956
|
when :simulator
|
|
@@ -914,9 +963,25 @@ module Aspera
|
|
|
914
963
|
server.mount(uri.path, NodeSimulatorServlet, parameters[:credentials], transfer)
|
|
915
964
|
server.start
|
|
916
965
|
return Main.result_status('Simulator terminated')
|
|
917
|
-
end
|
|
966
|
+
end
|
|
918
967
|
raise 'ERROR: shall not reach this line'
|
|
919
968
|
end
|
|
969
|
+
|
|
970
|
+
private
|
|
971
|
+
|
|
972
|
+
# get remaining path arguments from command line, and add prefix
|
|
973
|
+
def get_all_arguments_with_prefix(path_prefix, name)
|
|
974
|
+
path_args = options.get_next_argument(name, multiple: true)
|
|
975
|
+
return path_args if path_prefix.nil?
|
|
976
|
+
return path_args.map {|p| File.join(path_prefix, p)}
|
|
977
|
+
end
|
|
978
|
+
|
|
979
|
+
# get next path argument from command line, and add prefix
|
|
980
|
+
def get_one_argument_with_prefix(path_prefix, name)
|
|
981
|
+
path_arg = options.get_next_argument(name, validation: String)
|
|
982
|
+
return path_arg if path_prefix.nil?
|
|
983
|
+
return File.join(path_prefix, path_arg)
|
|
984
|
+
end
|
|
920
985
|
end
|
|
921
986
|
end
|
|
922
987
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'aspera/cli/basic_auth_plugin'
|
|
4
|
+
require 'aspera/cli/special_values'
|
|
4
5
|
require 'aspera/nagios'
|
|
5
6
|
require 'aspera/log'
|
|
6
7
|
require 'aspera/assert'
|
|
@@ -60,33 +61,37 @@ module Aspera
|
|
|
60
61
|
|
|
61
62
|
ACTIONS = %i[health info workflow plugins processes].freeze
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
# call orchestrator api
|
|
65
|
+
# @param endpoint [String] the endpoint to call
|
|
66
|
+
# @param prefix [String] the prefix to add to the endpoint
|
|
67
|
+
# @param id [String] the id to add to the endpoint
|
|
68
|
+
# @param ret_style [Symbol] the return style, :header, :arg, :ext(extension)
|
|
69
|
+
# @param format [String] the format to request, 'json', 'xml', nil
|
|
70
|
+
# @param args [Hash] the arguments to pass
|
|
71
|
+
# @param xml_arrays [Boolean] if true, force arrays in xml parsing
|
|
72
|
+
def call_ao(endpoint, prefix: 'api', id: nil, ret_style: nil, format: 'json', args: nil, xml_arrays: true)
|
|
65
73
|
# calls are GET
|
|
66
74
|
call_args = {operation: 'GET', subpath: endpoint}
|
|
67
75
|
# specify prefix if necessary
|
|
68
|
-
call_args[:subpath] = "#{
|
|
76
|
+
call_args[:subpath] = "#{prefix}/#{call_args[:subpath]}" unless prefix.nil?
|
|
69
77
|
# specify id if necessary
|
|
70
|
-
call_args[:subpath] = "#{call_args[:subpath]}/#{
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
format = 'json'
|
|
74
|
-
format = opt[:format] if opt.key?(:format)
|
|
75
|
-
call_args[:url_params] = opt[:args] unless opt[:args].nil?
|
|
78
|
+
call_args[:subpath] = "#{call_args[:subpath]}/#{id}" unless id.nil?
|
|
79
|
+
ret_style = options.get_option(:ret_style, mandatory: true) if ret_style.nil?
|
|
80
|
+
call_args[:query] = args unless args.nil?
|
|
76
81
|
unless format.nil?
|
|
77
|
-
case
|
|
82
|
+
case ret_style
|
|
78
83
|
when :header
|
|
79
84
|
call_args[:headers] = {'Accept' => "application/#{format}" }
|
|
80
85
|
when :arg
|
|
81
|
-
call_args[:
|
|
82
|
-
call_args[:
|
|
86
|
+
call_args[:query] ||= {}
|
|
87
|
+
call_args[:query][:format] = format
|
|
83
88
|
when :ext
|
|
84
89
|
call_args[:subpath] = "#{call_args[:subpath]}.#{format}"
|
|
85
|
-
else Aspera.error_unexpected_value(
|
|
90
|
+
else Aspera.error_unexpected_value(ret_style)
|
|
86
91
|
end
|
|
87
92
|
end
|
|
88
93
|
result = @api_orch.call(**call_args)
|
|
89
|
-
result[:data] = XmlSimple.xml_in(result[:http].body,
|
|
94
|
+
result[:data] = XmlSimple.xml_in(result[:http].body, {'ForceArray' => xml_arrays}) if format.eql?('xml')
|
|
90
95
|
Log.log.debug{Log.dump(:data, result[:data])}
|
|
91
96
|
return result
|
|
92
97
|
end
|
|
@@ -121,7 +126,7 @@ module Aspera
|
|
|
121
126
|
when :health
|
|
122
127
|
nagios = Nagios.new
|
|
123
128
|
begin
|
|
124
|
-
info = call_ao('remote_node_ping', format: 'xml',
|
|
129
|
+
info = call_ao('remote_node_ping', format: 'xml', xml_arrays: false)[:data]
|
|
125
130
|
nagios.add_ok('api', 'accessible')
|
|
126
131
|
nagios.check_product_version('api', 'orchestrator', info['orchestrator-version'])
|
|
127
132
|
rescue StandardError => e
|
|
@@ -129,7 +134,7 @@ module Aspera
|
|
|
129
134
|
end
|
|
130
135
|
return nagios.result
|
|
131
136
|
when :info
|
|
132
|
-
result = call_ao('remote_node_ping', format: 'xml',
|
|
137
|
+
result = call_ao('remote_node_ping', format: 'xml', xml_arrays: false)[:data]
|
|
133
138
|
return {type: :single_object, data: result}
|
|
134
139
|
when :processes
|
|
135
140
|
# TODO: Bug ? API has only XML format
|
|
@@ -146,9 +151,8 @@ module Aspera
|
|
|
146
151
|
end
|
|
147
152
|
case command
|
|
148
153
|
when :status
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
result = call_ao('workflows_status', call_opts)[:data]
|
|
154
|
+
wf_id = nil if wf_id.eql?(SpecialValues::ALL)
|
|
155
|
+
result = call_ao('workflows_status', id: wf_id)[:data]
|
|
152
156
|
return {type: :object_list, data: result['workflows']['workflow']}
|
|
153
157
|
when :list
|
|
154
158
|
result = call_ao('workflows_list', id: 0)[:data]
|
|
@@ -172,9 +176,8 @@ module Aspera
|
|
|
172
176
|
data: nil
|
|
173
177
|
}
|
|
174
178
|
call_params = {format: :json}
|
|
175
|
-
override_accept = nil
|
|
176
179
|
# get external parameters if any
|
|
177
|
-
options.get_next_argument('external_parameters', mandatory: false,
|
|
180
|
+
options.get_next_argument('external_parameters', mandatory: false, validation: Hash, default: {}).each do |name, value|
|
|
178
181
|
call_params["external_parameters[#{name}]"] = value
|
|
179
182
|
end
|
|
180
183
|
# synchronous call ?
|
|
@@ -192,15 +195,15 @@ module Aspera
|
|
|
192
195
|
end
|
|
193
196
|
if call_params['synchronous']
|
|
194
197
|
result[:type] = :text
|
|
195
|
-
override_accept = 'text/plain'
|
|
196
198
|
end
|
|
197
|
-
result[:data] = call_ao('initiate', id: wf_id, args: call_params
|
|
199
|
+
result[:data] = call_ao('initiate', id: wf_id, args: call_params)[:data]
|
|
198
200
|
return result
|
|
199
|
-
end
|
|
201
|
+
end
|
|
200
202
|
else Aspera.error_unexpected_value(command)
|
|
201
|
-
end
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
private :call_ao
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
@@ -128,7 +128,11 @@ module Aspera
|
|
|
128
128
|
def get_folder_entries(file_id, request_args=nil)
|
|
129
129
|
headers = {'Accept' => 'application/json'}
|
|
130
130
|
headers['X-Aspera-Cache-Control'] = 'no-cache' if @option_folder_reset_cache.eql?(:header)
|
|
131
|
-
return @api_node.call(
|
|
131
|
+
return @api_node.call(
|
|
132
|
+
operation: 'GET',
|
|
133
|
+
subpath: "files/#{file_id}/files",
|
|
134
|
+
headers: headers,
|
|
135
|
+
query: request_args)[:data]
|
|
132
136
|
# return @api_node.read("files/#{file_id}/files",request_args)[:data]
|
|
133
137
|
end
|
|
134
138
|
|
|
@@ -338,7 +342,7 @@ module Aspera
|
|
|
338
342
|
rescue StandardError => e
|
|
339
343
|
Log.log.error{"Ignore: #{e.message}"}
|
|
340
344
|
Log.log.debug(e.backtrace.join("\n").red)
|
|
341
|
-
end
|
|
345
|
+
end
|
|
342
346
|
|
|
343
347
|
# scan all files in provided folder entry
|
|
344
348
|
# @param top_path subpath to start folder scan inside
|
|
@@ -485,7 +489,7 @@ module Aspera
|
|
|
485
489
|
return Main.result_status('Tools validated')
|
|
486
490
|
when :test, :show
|
|
487
491
|
source = options.get_next_argument('source file')
|
|
488
|
-
format = options.get_next_argument('format',
|
|
492
|
+
format = options.get_next_argument('format', accept_list: Aspera::Preview::Generator::PREVIEW_FORMATS, default: :png)
|
|
489
493
|
generated_file_path = preview_filename(format, options.get_option(:base))
|
|
490
494
|
g = Aspera::Preview::Generator.new(source, generated_file_path, @gen_options, @tmp_folder, nil)
|
|
491
495
|
g.generate
|
|
@@ -232,7 +232,7 @@ module Aspera
|
|
|
232
232
|
when *TRANSFER_COMMANDS
|
|
233
233
|
return execute_transfer(command, server_transfer_spec)
|
|
234
234
|
when *AsCmd::OPERATIONS
|
|
235
|
-
command_arguments = options.get_next_argument('ascmd command arguments',
|
|
235
|
+
command_arguments = options.get_next_argument('ascmd command arguments', multiple: true, mandatory: false)
|
|
236
236
|
ascmd = AsCmd.new(ascmd_executor)
|
|
237
237
|
begin
|
|
238
238
|
result = ascmd.execute_single(command, command_arguments)
|
|
@@ -251,8 +251,8 @@ module Aspera
|
|
|
251
251
|
end
|
|
252
252
|
else Aspera.error_unreachable_line
|
|
253
253
|
end
|
|
254
|
-
end
|
|
255
|
-
end
|
|
256
|
-
end
|
|
257
|
-
end
|
|
258
|
-
end
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|