aspera-cli 4.17.0 → 4.18.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +2 -4
- data/CHANGELOG.md +23 -0
- data/CONTRIBUTING.md +15 -1
- data/README.md +620 -378
- data/bin/ascli +5 -0
- data/bin/asession +2 -2
- data/lib/aspera/agent/alpha.rb +6 -4
- data/lib/aspera/agent/base.rb +9 -6
- data/lib/aspera/agent/connect.rb +4 -4
- 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 +339 -0
- data/lib/aspera/api/node.rb +34 -21
- 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/cli/basic_auth_plugin.rb +5 -9
- data/lib/aspera/cli/extended_value.rb +12 -6
- data/lib/aspera/cli/formatter.rb +155 -65
- data/lib/aspera/cli/hints.rb +18 -0
- data/lib/aspera/cli/main.rb +22 -29
- data/lib/aspera/cli/manager.rb +53 -36
- data/lib/aspera/cli/plugin.rb +26 -17
- 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 +141 -131
- data/lib/aspera/cli/plugins/ats.rb +1 -1
- data/lib/aspera/cli/plugins/config.rb +52 -46
- data/lib/aspera/cli/plugins/console.rb +8 -5
- data/lib/aspera/cli/plugins/faspex.rb +27 -19
- data/lib/aspera/cli/plugins/faspex5.rb +222 -149
- 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 +86 -29
- data/lib/aspera/cli/plugins/orchestrator.rb +31 -29
- data/lib/aspera/cli/plugins/preview.rb +6 -2
- data/lib/aspera/cli/plugins/server.rb +5 -5
- data/lib/aspera/cli/plugins/shares.rb +16 -14
- data/lib/aspera/cli/sync_actions.rb +6 -6
- data/lib/aspera/cli/transfer_agent.rb +5 -4
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/environment.rb +7 -6
- 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/open_application.rb +5 -7
- 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 +60 -74
- 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 +5 -3
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/plugins/bss.rb +0 -71
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'aspera/rest'
|
4
|
+
require 'aspera/nagios'
|
5
|
+
require 'aspera/cli/basic_auth_plugin'
|
6
|
+
|
7
|
+
module Aspera
|
8
|
+
module Cli
|
9
|
+
module Plugins
|
10
|
+
class Faspio < BasicAuthPlugin
|
11
|
+
class << self
|
12
|
+
def application_name
|
13
|
+
'faspio Gateway'
|
14
|
+
end
|
15
|
+
|
16
|
+
def detect(base_url)
|
17
|
+
api = Rest.new(base_url: base_url)
|
18
|
+
ping_result = api.read('ping')
|
19
|
+
server_type = ping_result[:http]['Server']
|
20
|
+
return nil unless ping_result[:data].is_a?(Hash) && ping_result[:data].empty?
|
21
|
+
return nil unless server_type.is_a?(String) && server_type.include?('faspio')
|
22
|
+
return {
|
23
|
+
version: server_type.gsub(%r{^.*/}, ''),
|
24
|
+
url: base_url
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
ACTIONS = %i[health bridges].freeze
|
29
|
+
|
30
|
+
def initialize(**env)
|
31
|
+
super
|
32
|
+
options.declare(:auth, 'OAuth type of authentication', values: %i[jwt basic])
|
33
|
+
options.declare(:client_id, 'OAuth client identifier')
|
34
|
+
options.declare(:private_key, 'OAuth JWT RSA private key PEM value (prefix file path with @file:)')
|
35
|
+
options.declare(:passphrase, 'OAuth JWT RSA private key passphrase')
|
36
|
+
options.parse_options!
|
37
|
+
end
|
38
|
+
|
39
|
+
def execute_action
|
40
|
+
base_url = options.get_option(:url, mandatory: true)
|
41
|
+
api =
|
42
|
+
case options.get_option(:auth, mandatory: true)
|
43
|
+
when :basic
|
44
|
+
basic_auth_api
|
45
|
+
when :jwt
|
46
|
+
app_client_id = options.get_option(:client_id, mandatory: true)
|
47
|
+
Rest.new(
|
48
|
+
base_url: base_url,
|
49
|
+
auth: {
|
50
|
+
type: :oauth2,
|
51
|
+
grant_method: :jwt,
|
52
|
+
base_url: "#{base_url}/auth",
|
53
|
+
client_id: app_client_id,
|
54
|
+
use_query: true,
|
55
|
+
payload: {
|
56
|
+
iss: app_client_id, # issuer
|
57
|
+
sub: app_client_id # subject
|
58
|
+
},
|
59
|
+
private_key_obj: OpenSSL::PKey::RSA.new(options.get_option(:private_key, mandatory: true), options.get_option(:passphrase)),
|
60
|
+
headers: {typ: 'JWT'}
|
61
|
+
})
|
62
|
+
end
|
63
|
+
command = options.get_next_command(ACTIONS)
|
64
|
+
case command
|
65
|
+
when :health
|
66
|
+
nagios = Nagios.new
|
67
|
+
begin
|
68
|
+
result = api.read('ping')[:data]
|
69
|
+
if result.is_a?(Hash) && result.empty?
|
70
|
+
nagios.add_ok('api', 'answered ok')
|
71
|
+
else
|
72
|
+
nagios.add_critical('api', 'not expected answer')
|
73
|
+
end
|
74
|
+
rescue StandardError => e
|
75
|
+
nagios.add_critical('api', e.to_s)
|
76
|
+
end
|
77
|
+
return nagios.result
|
78
|
+
when :bridges
|
79
|
+
return entity_action(api, 'bridges')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -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
|
@@ -44,7 +44,8 @@ module Aspera
|
|
44
44
|
next unless result[:http].body.eql?('')
|
45
45
|
url_length = -2 - test_endpoint.length
|
46
46
|
return {
|
47
|
-
url:
|
47
|
+
url: result[:http].uri.to_s[0..url_length],
|
48
|
+
version: 'requires authentication'
|
48
49
|
}
|
49
50
|
rescue StandardError => e
|
50
51
|
error = e
|
@@ -92,7 +93,7 @@ module Aspera
|
|
92
93
|
SEARCH_REMOVE_FIELDS = %w[basename permissions].freeze
|
93
94
|
|
94
95
|
# actions in execute_command_gen3
|
95
|
-
COMMANDS_GEN3 = %i[search space mkdir mklink mkfile rename delete browse upload download http_node_download sync]
|
96
|
+
COMMANDS_GEN3 = %i[search space mkdir mklink mkfile rename delete browse upload download http_node_download sync transport]
|
96
97
|
|
97
98
|
BASE_ACTIONS = %i[api_details].concat(COMMANDS_GEN3).freeze
|
98
99
|
|
@@ -187,6 +188,68 @@ module Aspera
|
|
187
188
|
raise StandardError, 'expect: nil, String or Array'
|
188
189
|
end
|
189
190
|
|
191
|
+
# directory: node, container: shares
|
192
|
+
FOLDER_TYPE = %w[directory container].freeze
|
193
|
+
|
194
|
+
def browse_gen3(prefix_path)
|
195
|
+
folders_to_process = [get_next_arg_add_prefix(prefix_path, 'path')]
|
196
|
+
query = options.get_option(:query, default: {})
|
197
|
+
# special parameter: max number of entries in result
|
198
|
+
max_items = query.delete('max')
|
199
|
+
# special parameter: recursive browsing
|
200
|
+
recursive = query.delete('recursive')
|
201
|
+
# special parameter: only return one entry for the path, even if folder
|
202
|
+
only_path = query.delete('self')
|
203
|
+
# allow user to specify a single call, and not recursive
|
204
|
+
single_call = query.key?('skip')
|
205
|
+
# API default is 100, so use 1000 for default
|
206
|
+
query['count'] ||= 1000
|
207
|
+
raise Cli::BadArgument, 'options recursive and skip cannot be used together' if recursive && single_call
|
208
|
+
all_items = []
|
209
|
+
until folders_to_process.empty?
|
210
|
+
path = folders_to_process.shift
|
211
|
+
query['path'] = path
|
212
|
+
offset = 0
|
213
|
+
total_count = nil
|
214
|
+
result = nil
|
215
|
+
loop do
|
216
|
+
# example: send_result={'items'=>[{'file'=>"filename1","permissions"=>[{'name'=>'read'},{'name'=>'write'}]}]}
|
217
|
+
response = @api_node.call(
|
218
|
+
operation: 'POST',
|
219
|
+
subpath: 'files/browse',
|
220
|
+
headers: {'Accept' => 'application/json'},
|
221
|
+
body: query,
|
222
|
+
body_type: :json)
|
223
|
+
# 'file','symbolic_link'
|
224
|
+
if only_path || !FOLDER_TYPE.include?(response[:data]['self']['type'])
|
225
|
+
result = { type: :single_object, data: response[:data]['self']}
|
226
|
+
break
|
227
|
+
end
|
228
|
+
items = response[:data]['items']
|
229
|
+
total_count ||= response[:data]['total_count']
|
230
|
+
all_items.concat(items)
|
231
|
+
if single_call
|
232
|
+
formatter.display_item_count(response[:data]['item_count'], total_count)
|
233
|
+
break
|
234
|
+
end
|
235
|
+
if recursive
|
236
|
+
folders_to_process.concat(items.select{|i|FOLDER_TYPE.include?(i['type'])}.map{|i|i['path']})
|
237
|
+
end
|
238
|
+
if !max_items.nil? && (all_items.count >= max_items)
|
239
|
+
all_items = all_items.slice(0, max_items) if all_items.count > max_items
|
240
|
+
break
|
241
|
+
end
|
242
|
+
break if all_items.count >= total_count
|
243
|
+
offset += items.count
|
244
|
+
query['skip'] = offset
|
245
|
+
formatter.long_operation_running(all_items.count)
|
246
|
+
end
|
247
|
+
query.delete('skip')
|
248
|
+
end
|
249
|
+
result ||= {type: :object_list, data: all_items}
|
250
|
+
return c_result_remove_prefix_path(result, 'path', prefix_path)
|
251
|
+
end
|
252
|
+
|
190
253
|
# file and folder related commands
|
191
254
|
def execute_command_gen3(command, prefix_path)
|
192
255
|
case command
|
@@ -235,20 +298,7 @@ module Aspera
|
|
235
298
|
resp = @api_node.create('files/rename', { 'paths' => [{ 'path' => path_base, 'source' => path_src, 'destination' => path_dst }] })
|
236
299
|
return c_result_translate_rem_prefix(resp, 'entry', 'moved', prefix_path)
|
237
300
|
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)
|
301
|
+
return browse_gen3(prefix_path)
|
252
302
|
when :sync
|
253
303
|
return execute_sync_action do |sync_direction, local_path, remote_path|
|
254
304
|
# Gen3 API
|
@@ -303,6 +353,8 @@ module Aspera
|
|
303
353
|
subpath: "files/#{URI.encode_www_form_component(remote_path)}/contents",
|
304
354
|
save_to_file: File.join(transfer.destination_folder(Transfer::Spec::DIRECTION_RECEIVE), file_name))
|
305
355
|
return Main.result_status("downloaded: #{file_name}")
|
356
|
+
when :transport
|
357
|
+
return {type: :single_object, data: @api_node.transport_params}
|
306
358
|
end
|
307
359
|
Aspera.error_unreachable_line
|
308
360
|
end
|
@@ -358,9 +410,10 @@ module Aspera
|
|
358
410
|
begin
|
359
411
|
@api_node.call(
|
360
412
|
operation: 'POST',
|
361
|
-
subpath:
|
362
|
-
headers:
|
363
|
-
|
413
|
+
subpath: 'services/soap/Transfer-201210',
|
414
|
+
headers: {'Content-Type' => 'text/xml;charset=UTF-8', 'SOAPAction' => 'FASPSessionNET-200911#GetSessionInfo'},
|
415
|
+
body: CENTRAL_SOAP_API_TEST,
|
416
|
+
body_type: :text)[:http].body
|
364
417
|
nagios.add_ok('central', 'accessible by node')
|
365
418
|
rescue StandardError => e
|
366
419
|
nagios.add_critical('central', e.to_s)
|
@@ -420,7 +473,7 @@ module Aspera
|
|
420
473
|
result[:password] = apifid[:api].auth_params[:password]
|
421
474
|
when :oauth2
|
422
475
|
result[:username] = apifid[:api].params[:headers][Api::Node::HEADER_X_ASPERA_ACCESS_KEY]
|
423
|
-
result[:password] = apifid[:api].
|
476
|
+
result[:password] = apifid[:api].oauth.token
|
424
477
|
else Aspera.error_unreachable_line
|
425
478
|
end
|
426
479
|
return {type: :single_object, data: result} if command_repo.eql?(:node_info)
|
@@ -431,7 +484,7 @@ module Aspera
|
|
431
484
|
apifid = @api_node.resolve_api_fid(top_file_id, options.get_next_argument('path'))
|
432
485
|
file_info = apifid[:api].read("files/#{apifid[:file_id]}")[:data]
|
433
486
|
if file_info['type'].eql?('folder')
|
434
|
-
result = apifid[:api].read("files/#{apifid[:file_id]}/files",
|
487
|
+
result = apifid[:api].read("files/#{apifid[:file_id]}/files", query_read_delete)
|
435
488
|
items = result[:data]
|
436
489
|
formatter.display_item_count(result[:data].length, result[:http]['X-Total-Count'])
|
437
490
|
else
|
@@ -538,7 +591,7 @@ module Aspera
|
|
538
591
|
subpath: "files/#{apifid[:file_id]}/preview",
|
539
592
|
headers: {'Accept' => 'image/png'}
|
540
593
|
)
|
541
|
-
return Main.
|
594
|
+
return Main.result_image(result[:http].body, formatter: formatter)
|
542
595
|
when :permission
|
543
596
|
apifid = apifid_from_next_arg(top_file_id)
|
544
597
|
command_perm = options.get_next_command(%i[list create delete])
|
@@ -574,9 +627,9 @@ module Aspera
|
|
574
627
|
else Aspera.error_unreachable_line
|
575
628
|
end
|
576
629
|
else Aspera.error_unreachable_line
|
577
|
-
end
|
630
|
+
end
|
578
631
|
Aspera.error_unreachable_line
|
579
|
-
end
|
632
|
+
end
|
580
633
|
|
581
634
|
# This is older API
|
582
635
|
def execute_async
|
@@ -695,11 +748,15 @@ module Aspera
|
|
695
748
|
when *Plugin::ALL_OPS then return entity_command(sync_command, @api_node, 'asyncs', item_list_key: 'ids'){|field, value|ssync_lookup(field, value)}
|
696
749
|
else
|
697
750
|
asyncs_id = instance_identifier {|field, value|ssync_lookup(field, value)}
|
698
|
-
parameters = nil
|
699
751
|
if %i[start stop].include?(sync_command)
|
700
|
-
@api_node.
|
752
|
+
@api_node.call(
|
753
|
+
operation: 'POST',
|
754
|
+
subpath: "asyncs/#{asyncs_id}/#{sync_command}",
|
755
|
+
body: '',
|
756
|
+
body_type: :text)[:http].body
|
701
757
|
return Main.result_status('Done')
|
702
758
|
end
|
759
|
+
parameters = nil
|
703
760
|
parameters = query_option(default: {}) if %i[bandwidth counters files].include?(sync_command)
|
704
761
|
return { type: :single_object, data: @api_node.read("asyncs/#{asyncs_id}/#{sync_command}", parameters)[:data] }
|
705
762
|
end
|
@@ -707,7 +764,7 @@ module Aspera
|
|
707
764
|
command = options.get_next_command(%i[list create show modify cancel])
|
708
765
|
case command
|
709
766
|
when :list
|
710
|
-
resp = @api_node.read('ops/transfers',
|
767
|
+
resp = @api_node.read('ops/transfers', query_read_delete)
|
711
768
|
return { type: :object_list, data: resp[:data], fields: %w[id status] } # TODO: useful?
|
712
769
|
when :create
|
713
770
|
resp = @api_node.create('streams', value_create_modify(command: command))
|
@@ -841,7 +898,7 @@ module Aspera
|
|
841
898
|
resp = @api_node.create(res_class_path, value_create_modify(command: command))
|
842
899
|
return Main.result_status("#{resp[:data]['id']} created")
|
843
900
|
when :list
|
844
|
-
resp = @api_node.read(res_class_path,
|
901
|
+
resp = @api_node.read(res_class_path, query_read_delete)
|
845
902
|
return { type: :value_list, data: resp[:data]['ids'], name: 'id' }
|
846
903
|
when :show
|
847
904
|
return { type: :single_object, data: @api_node.read(one_res_path)[:data]}
|
@@ -914,7 +971,7 @@ module Aspera
|
|
914
971
|
server.mount(uri.path, NodeSimulatorServlet, parameters[:credentials], transfer)
|
915
972
|
server.start
|
916
973
|
return Main.result_status('Simulator terminated')
|
917
|
-
end
|
974
|
+
end
|
918
975
|
raise 'ERROR: shall not reach this line'
|
919
976
|
end
|
920
977
|
end
|
@@ -60,33 +60,37 @@ module Aspera
|
|
60
60
|
|
61
61
|
ACTIONS = %i[health info workflow plugins processes].freeze
|
62
62
|
|
63
|
-
|
64
|
-
|
63
|
+
# call orchestrator api
|
64
|
+
# @param endpoint [String] the endpoint to call
|
65
|
+
# @param prefix [String] the prefix to add to the endpoint
|
66
|
+
# @param id [String] the id to add to the endpoint
|
67
|
+
# @param ret_style [Symbol] the return style, :header, :arg, :ext(extension)
|
68
|
+
# @param format [String] the format to request, 'json', 'xml', nil
|
69
|
+
# @param args [Hash] the arguments to pass
|
70
|
+
# @param xml_arrays [Boolean] if true, force arrays in xml parsing
|
71
|
+
def call_ao(endpoint, prefix: 'api', id: nil, ret_style: nil, format: 'json', args: nil, xml_arrays: true)
|
65
72
|
# calls are GET
|
66
73
|
call_args = {operation: 'GET', subpath: endpoint}
|
67
74
|
# specify prefix if necessary
|
68
|
-
call_args[:subpath] = "#{
|
75
|
+
call_args[:subpath] = "#{prefix}/#{call_args[:subpath]}" unless prefix.nil?
|
69
76
|
# 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?
|
77
|
+
call_args[:subpath] = "#{call_args[:subpath]}/#{id}" unless id.nil?
|
78
|
+
ret_style = options.get_option(:ret_style, mandatory: true) if ret_style.nil?
|
79
|
+
call_args[:query] = args unless args.nil?
|
76
80
|
unless format.nil?
|
77
|
-
case
|
81
|
+
case ret_style
|
78
82
|
when :header
|
79
83
|
call_args[:headers] = {'Accept' => "application/#{format}" }
|
80
84
|
when :arg
|
81
|
-
call_args[:
|
82
|
-
call_args[:
|
85
|
+
call_args[:query] ||= {}
|
86
|
+
call_args[:query][:format] = format
|
83
87
|
when :ext
|
84
88
|
call_args[:subpath] = "#{call_args[:subpath]}.#{format}"
|
85
|
-
else Aspera.error_unexpected_value(
|
89
|
+
else Aspera.error_unexpected_value(ret_style)
|
86
90
|
end
|
87
91
|
end
|
88
92
|
result = @api_orch.call(**call_args)
|
89
|
-
result[:data] = XmlSimple.xml_in(result[:http].body,
|
93
|
+
result[:data] = XmlSimple.xml_in(result[:http].body, {'ForceArray' => xml_arrays}) if format.eql?('xml')
|
90
94
|
Log.log.debug{Log.dump(:data, result[:data])}
|
91
95
|
return result
|
92
96
|
end
|
@@ -121,7 +125,7 @@ module Aspera
|
|
121
125
|
when :health
|
122
126
|
nagios = Nagios.new
|
123
127
|
begin
|
124
|
-
info = call_ao('remote_node_ping', format: 'xml',
|
128
|
+
info = call_ao('remote_node_ping', format: 'xml', xml_arrays: false)[:data]
|
125
129
|
nagios.add_ok('api', 'accessible')
|
126
130
|
nagios.check_product_version('api', 'orchestrator', info['orchestrator-version'])
|
127
131
|
rescue StandardError => e
|
@@ -129,7 +133,7 @@ module Aspera
|
|
129
133
|
end
|
130
134
|
return nagios.result
|
131
135
|
when :info
|
132
|
-
result = call_ao('remote_node_ping', format: 'xml',
|
136
|
+
result = call_ao('remote_node_ping', format: 'xml', xml_arrays: false)[:data]
|
133
137
|
return {type: :single_object, data: result}
|
134
138
|
when :processes
|
135
139
|
# TODO: Bug ? API has only XML format
|
@@ -146,9 +150,8 @@ module Aspera
|
|
146
150
|
end
|
147
151
|
case command
|
148
152
|
when :status
|
149
|
-
|
150
|
-
|
151
|
-
result = call_ao('workflows_status', call_opts)[:data]
|
153
|
+
wf_id = nil if wf_id.eql?(ExtendedValue::ALL)
|
154
|
+
result = call_ao('workflows_status', id: wf_id)[:data]
|
152
155
|
return {type: :object_list, data: result['workflows']['workflow']}
|
153
156
|
when :list
|
154
157
|
result = call_ao('workflows_list', id: 0)[:data]
|
@@ -172,7 +175,6 @@ module Aspera
|
|
172
175
|
data: nil
|
173
176
|
}
|
174
177
|
call_params = {format: :json}
|
175
|
-
override_accept = nil
|
176
178
|
# get external parameters if any
|
177
179
|
options.get_next_argument('external_parameters', mandatory: false, type: Hash, default: {}).each do |name, value|
|
178
180
|
call_params["external_parameters[#{name}]"] = value
|
@@ -192,15 +194,15 @@ module Aspera
|
|
192
194
|
end
|
193
195
|
if call_params['synchronous']
|
194
196
|
result[:type] = :text
|
195
|
-
override_accept = 'text/plain'
|
196
197
|
end
|
197
|
-
result[:data] = call_ao('initiate', id: wf_id, args: call_params
|
198
|
+
result[:data] = call_ao('initiate', id: wf_id, args: call_params)[:data]
|
198
199
|
return result
|
199
|
-
end
|
200
|
+
end
|
200
201
|
else Aspera.error_unexpected_value(command)
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
private :call_ao
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
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
|
@@ -7,7 +7,7 @@ module Aspera
|
|
7
7
|
module Plugins
|
8
8
|
# Plugin for Aspera Shares v1
|
9
9
|
class Shares < Cli::BasicAuthPlugin
|
10
|
-
|
10
|
+
NODE_API_PREFIX = 'node_api'
|
11
11
|
class << self
|
12
12
|
def detect(address_or_url)
|
13
13
|
address_or_url = "https://#{address_or_url}" unless address_or_url.match?(%r{^[a-z]{1,6}://})
|
@@ -16,7 +16,7 @@ module Aspera
|
|
16
16
|
begin
|
17
17
|
# shall fail: shares requires auth, but we check error message
|
18
18
|
# TODO: use ping instead ?
|
19
|
-
api.read("#{
|
19
|
+
api.read("#{NODE_API_PREFIX}/app")
|
20
20
|
rescue RestCallError => e
|
21
21
|
if e.response.code.to_s.eql?('401') && e.response.body.eql?('{"error":{"user_message":"API user authentication failed"}}')
|
22
22
|
found = true
|
@@ -64,22 +64,24 @@ module Aspera
|
|
64
64
|
when :health
|
65
65
|
nagios = Nagios.new
|
66
66
|
begin
|
67
|
-
Rest
|
68
|
-
.new(base_url: "#{options.get_option(:url, mandatory: true)}/#{
|
67
|
+
res = Rest
|
68
|
+
.new(base_url: "#{options.get_option(:url, mandatory: true)}/#{NODE_API_PREFIX}")
|
69
69
|
.call(
|
70
70
|
operation: 'GET',
|
71
71
|
subpath: 'ping',
|
72
|
-
headers: {'content-type': 'application/json'}
|
73
|
-
|
72
|
+
headers: {'content-type': 'application/json'})
|
73
|
+
raise 'Shares not detected' unless res[:http].body.eql?(' ')
|
74
74
|
nagios.add_ok('shares api', 'accessible')
|
75
75
|
rescue StandardError => e
|
76
|
-
nagios.add_critical('
|
76
|
+
nagios.add_critical('API', e.to_s)
|
77
77
|
end
|
78
78
|
return nagios.result
|
79
79
|
when :repository, :files
|
80
|
-
api_shares_node = basic_auth_api(
|
80
|
+
api_shares_node = basic_auth_api(NODE_API_PREFIX)
|
81
81
|
repo_command = options.get_next_command(Node::COMMANDS_SHARES)
|
82
|
-
return Node
|
82
|
+
return Node
|
83
|
+
.new(**init_params, api: api_shares_node)
|
84
|
+
.execute_action(repo_command)
|
83
85
|
when :admin
|
84
86
|
api_shares_admin = basic_auth_api('api/v1')
|
85
87
|
admin_command = options.get_next_command(%i[node share transfer_settings user group].freeze)
|
@@ -150,8 +152,8 @@ module Aspera
|
|
150
152
|
end
|
151
153
|
end
|
152
154
|
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -60,9 +60,9 @@ module Aspera
|
|
60
60
|
sync_session_name = options.get_next_argument('name of sync session', mandatory: false, type: String)
|
61
61
|
async_params = options.get_option(:sync_info, mandatory: true)
|
62
62
|
return {type: :single_object, data: Transfer::Sync.admin_status(async_params, sync_session_name)}
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -26,6 +26,7 @@ module Aspera
|
|
26
26
|
|
27
27
|
<%=ts.to_yaml%>
|
28
28
|
END_OF_TEMPLATE
|
29
|
+
CP4I_REMOTE_HOST_LB = 'N/A'
|
29
30
|
# % (formatting bug in eclipse)
|
30
31
|
private_constant :FILE_LIST_FROM_ARGS,
|
31
32
|
:FILE_LIST_FROM_TRANSFER_SPEC,
|
@@ -101,8 +102,6 @@ module Aspera
|
|
101
102
|
def agent_instance
|
102
103
|
return @agent unless @agent.nil?
|
103
104
|
agent_type = @opt_mgr.get_option(:transfer, mandatory: true)
|
104
|
-
# agent plugin is loaded on demand to avoid loading unnecessary dependencies
|
105
|
-
require "aspera/agent/#{agent_type}"
|
106
105
|
# set keys as symbols
|
107
106
|
agent_options = @opt_mgr.get_option(:transfer_info).symbolize_keys
|
108
107
|
# special cases
|
@@ -126,8 +125,7 @@ module Aspera
|
|
126
125
|
end
|
127
126
|
agent_options[:progress] = @config.progress_bar
|
128
127
|
# get agent instance
|
129
|
-
|
130
|
-
self.agent_instance = new_agent
|
128
|
+
self.agent_instance = Agent::Base.factory_create(agent_type, agent_options)
|
131
129
|
Log.log.debug{"transfer agent is a #{@agent.class}"}
|
132
130
|
return @agent
|
133
131
|
end
|
@@ -218,6 +216,9 @@ module Aspera
|
|
218
216
|
def start(transfer_spec, rest_token: nil)
|
219
217
|
# check parameters
|
220
218
|
Aspera.assert_type(transfer_spec, Hash){'transfer_spec'}
|
219
|
+
if transfer_spec['remote_host'].eql?(CP4I_REMOTE_HOST_LB)
|
220
|
+
raise "Wrong remote host: #{CP4I_REMOTE_HOST_LB}"
|
221
|
+
end
|
221
222
|
# process :src option
|
222
223
|
case transfer_spec['direction']
|
223
224
|
when Transfer::Spec::DIRECTION_RECEIVE
|
data/lib/aspera/cli/version.rb
CHANGED
data/lib/aspera/environment.rb
CHANGED
@@ -27,6 +27,7 @@ module Aspera
|
|
27
27
|
BYTES_PER_MEBIBIT = MEBI / BITS_PER_BYTE
|
28
28
|
|
29
29
|
class << self
|
30
|
+
@terminal_supports_unicode = nil
|
30
31
|
def ruby_version
|
31
32
|
return RbConfig::CONFIG['RUBY_PROGRAM_VERSION']
|
32
33
|
end
|
@@ -121,10 +122,10 @@ module Aspera
|
|
121
122
|
end
|
122
123
|
|
123
124
|
# @return true if we can display Unicode characters
|
124
|
-
def
|
125
|
-
@
|
126
|
-
return @
|
125
|
+
def terminal_supports_unicode?
|
126
|
+
@terminal_supports_unicode = terminal? && ENV.values_at('LC_ALL', 'LC_CTYPE', 'LANG').compact.first.include?('UTF-8') if @terminal_supports_unicode.nil?
|
127
|
+
return @terminal_supports_unicode
|
127
128
|
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|