aspera-cli 4.14.0 → 4.15.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/CHANGELOG.md +54 -3
- data/CONTRIBUTING.md +7 -7
- data/README.md +1457 -880
- data/bin/ascli +18 -9
- data/bin/asession +12 -14
- data/examples/proxy.pac +1 -1
- data/lib/aspera/aoc.rb +198 -127
- data/lib/aspera/ascmd.rb +24 -14
- 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 +47 -12
- data/lib/aspera/cli/formatter.rb +260 -171
- data/lib/aspera/cli/hints.rb +80 -0
- data/lib/aspera/cli/main.rb +101 -147
- data/lib/aspera/cli/manager.rb +160 -124
- data/lib/aspera/cli/plugin.rb +70 -59
- data/lib/aspera/cli/plugins/alee.rb +0 -1
- data/lib/aspera/cli/plugins/aoc.rb +239 -273
- data/lib/aspera/cli/plugins/ats.rb +8 -5
- data/lib/aspera/cli/plugins/bss.rb +2 -2
- data/lib/aspera/cli/plugins/config.rb +516 -375
- 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 +99 -84
- data/lib/aspera/cli/plugins/faspex5.rb +179 -148
- data/lib/aspera/cli/plugins/node.rb +219 -153
- data/lib/aspera/cli/plugins/orchestrator.rb +52 -17
- data/lib/aspera/cli/plugins/preview.rb +46 -32
- data/lib/aspera/cli/plugins/server.rb +57 -17
- data/lib/aspera/cli/plugins/shares.rb +34 -12
- data/lib/aspera/cli/sync_actions.rb +68 -0
- data/lib/aspera/cli/transfer_agent.rb +45 -55
- data/lib/aspera/cli/transfer_progress.rb +74 -0
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +3 -1
- data/lib/aspera/command_line_builder.rb +14 -11
- data/lib/aspera/cos_node.rb +3 -2
- data/lib/aspera/environment.rb +17 -6
- data/lib/aspera/fasp/agent_aspera.rb +126 -0
- data/lib/aspera/fasp/agent_base.rb +31 -77
- data/lib/aspera/fasp/agent_connect.rb +21 -22
- data/lib/aspera/fasp/agent_direct.rb +88 -102
- data/lib/aspera/fasp/agent_httpgw.rb +196 -192
- data/lib/aspera/fasp/agent_node.rb +41 -34
- data/lib/aspera/fasp/agent_trsdk.rb +75 -34
- data/lib/aspera/fasp/error_info.rb +2 -2
- data/lib/aspera/fasp/faux_file.rb +52 -0
- data/lib/aspera/fasp/installation.rb +43 -184
- data/lib/aspera/fasp/management.rb +244 -0
- data/lib/aspera/fasp/parameters.rb +59 -26
- data/lib/aspera/fasp/parameters.yaml +75 -8
- data/lib/aspera/fasp/products.rb +162 -0
- data/lib/aspera/fasp/transfer_spec.rb +1 -1
- data/lib/aspera/fasp/uri.rb +4 -4
- data/lib/aspera/faspex_gw.rb +2 -2
- data/lib/aspera/faspex_postproc.rb +2 -2
- data/lib/aspera/hash_ext.rb +2 -2
- data/lib/aspera/json_rpc.rb +49 -0
- data/lib/aspera/line_logger.rb +23 -0
- data/lib/aspera/log.rb +57 -16
- data/lib/aspera/node.rb +97 -14
- data/lib/aspera/oauth.rb +36 -18
- data/lib/aspera/open_application.rb +4 -4
- data/lib/aspera/persistency_folder.rb +2 -2
- data/lib/aspera/preview/file_types.rb +4 -2
- data/lib/aspera/preview/generator.rb +22 -35
- data/lib/aspera/preview/options.rb +2 -0
- data/lib/aspera/preview/terminal.rb +24 -13
- data/lib/aspera/preview/utils.rb +19 -26
- data/lib/aspera/rest.rb +103 -72
- data/lib/aspera/rest_call_error.rb +1 -1
- data/lib/aspera/rest_error_analyzer.rb +15 -14
- data/lib/aspera/rest_errors_aspera.rb +37 -34
- data/lib/aspera/secret_hider.rb +14 -16
- data/lib/aspera/ssh.rb +4 -1
- data/lib/aspera/sync.rb +128 -122
- data/lib/aspera/temp_file_manager.rb +10 -3
- data/lib/aspera/web_auth.rb +10 -7
- data/lib/aspera/web_server_simple.rb +9 -4
- data.tar.gz.sig +0 -0
- metadata +33 -15
- 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
@@ -7,6 +7,46 @@ module Aspera
|
|
7
7
|
module Cli
|
8
8
|
module Plugins
|
9
9
|
class Console < Aspera::Cli::BasicAuthPlugin
|
10
|
+
STANDARD_PATH = '/aspera/console'
|
11
|
+
class << self
|
12
|
+
def detect(address_or_url)
|
13
|
+
address_or_url = "https://#{address_or_url}" unless address_or_url.match?(%r{^[a-z]{1,6}://})
|
14
|
+
urls = [address_or_url]
|
15
|
+
urls.push("#{address_or_url}#{STANDARD_PATH}") unless address_or_url.end_with?(STANDARD_PATH)
|
16
|
+
|
17
|
+
urls.each do |base_url|
|
18
|
+
next unless base_url.start_with?('https://')
|
19
|
+
api = Rest.new(base_url: base_url, redirect_max: 2)
|
20
|
+
test_endpoint = 'login'
|
21
|
+
test_page = api.call({operation: 'GET', subpath: test_endpoint, url_params: {local: true}})
|
22
|
+
next unless test_page[:http].body.include?('Aspera Console')
|
23
|
+
version = 'unknown'
|
24
|
+
if (m = test_page[:http].body.match(/\(v([1-9]\..*)\)/))
|
25
|
+
version = m[1]
|
26
|
+
end
|
27
|
+
url = test_page[:http].uri.to_s
|
28
|
+
return {
|
29
|
+
version: version,
|
30
|
+
url: url[0..url.index(test_endpoint) - 2]
|
31
|
+
}
|
32
|
+
rescue StandardError => e
|
33
|
+
Log.log.debug{"detect error: #{e}"}
|
34
|
+
end
|
35
|
+
return nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def wizard(object:, private_key_path: nil, pub_key_pem: nil)
|
39
|
+
options = object.options
|
40
|
+
return {
|
41
|
+
preset_value: {
|
42
|
+
url: options.get_option(:url, mandatory: true),
|
43
|
+
username: options.get_option(:username, mandatory: true),
|
44
|
+
password: options.get_option(:password, mandatory: true)
|
45
|
+
},
|
46
|
+
test_args: 'transfer list'
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
10
50
|
DEFAULT_FILTER_AGE_SECONDS = 3 * 3600
|
11
51
|
private_constant :DEFAULT_FILTER_AGE_SECONDS
|
12
52
|
def initialize(env)
|
@@ -10,7 +10,6 @@ module Aspera
|
|
10
10
|
class Cos < Aspera::Cli::Plugin
|
11
11
|
def initialize(env)
|
12
12
|
super(env)
|
13
|
-
@service_creds = nil
|
14
13
|
options.declare(:bucket, 'Bucket name')
|
15
14
|
options.declare(:endpoint, 'Storage endpoint url')
|
16
15
|
options.declare(:apikey, 'Storage API key')
|
@@ -31,19 +30,19 @@ module Aspera
|
|
31
30
|
# get service credentials, Hash, e.g. @json:@file:...
|
32
31
|
service_credentials = options.get_option(:service_credentials)
|
33
32
|
storage_endpoint = options.get_option(:endpoint)
|
34
|
-
raise
|
35
|
-
raise
|
33
|
+
raise Cli::BadArgument, 'one of: endpoint or service_credentials is required' if service_credentials.nil? && storage_endpoint.nil?
|
34
|
+
raise Cli::BadArgument, 'endpoint and service_credentials are mutually exclusive' unless service_credentials.nil? || storage_endpoint.nil?
|
36
35
|
if service_credentials.nil?
|
37
36
|
service_api_key = options.get_option(:apikey, mandatory: true)
|
38
37
|
instance_id = options.get_option(:crn, mandatory: true)
|
39
38
|
else
|
40
|
-
params = CosNode.
|
39
|
+
params = CosNode.parameters_from_svc_credentials(service_credentials, options.get_option(:region, mandatory: true))
|
41
40
|
storage_endpoint = params[:storage_endpoint]
|
42
41
|
service_api_key = params[:service_api_key]
|
43
42
|
instance_id = params[:instance_id]
|
44
43
|
end
|
45
44
|
api_node = CosNode.new(bucket_name, storage_endpoint, instance_id, service_api_key, options.get_option(:identity, mandatory: true))
|
46
|
-
node_plugin = Node.new(@agents
|
45
|
+
node_plugin = Node.new(@agents, api: api_node)
|
47
46
|
command = options.get_next_command(Node::COMMANDS_COS)
|
48
47
|
return node_plugin.execute_action(command)
|
49
48
|
end
|
@@ -1,14 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# cspell:ignore passcode xrds workgroups dmembership wmembership
|
3
4
|
require 'aspera/cli/basic_auth_plugin'
|
4
5
|
require 'aspera/cli/plugins/node'
|
5
6
|
require 'aspera/cli/plugins/config'
|
6
7
|
require 'aspera/cli/extended_value'
|
7
8
|
require 'aspera/cli/transfer_agent'
|
8
|
-
require 'aspera/persistency_action_once'
|
9
|
-
require 'aspera/open_application'
|
10
9
|
require 'aspera/fasp/uri'
|
11
10
|
require 'aspera/fasp/transfer_spec'
|
11
|
+
require 'aspera/persistency_action_once'
|
12
|
+
require 'aspera/open_application'
|
12
13
|
require 'aspera/nagios'
|
13
14
|
require 'aspera/id_generator'
|
14
15
|
require 'xmlsimple'
|
@@ -32,45 +33,68 @@ module Aspera
|
|
32
33
|
ATOM_EXT_PARAMS = [MAX_ITEMS, MAX_PAGES].concat(ATOM_PARAMS).freeze
|
33
34
|
# sub path in url for public link delivery
|
34
35
|
PUB_LINK_EXTERNAL_MATCH = 'external_deliveries/'
|
36
|
+
STANDARD_PATH = '/aspera/faspex'
|
35
37
|
private_constant(*%i[KEY_NODE KEY_PATH PACKAGE_MATCH_FIELD ATOM_MAILBOXES ATOM_PARAMS ATOM_EXT_PARAMS PUB_LINK_EXTERNAL_MATCH])
|
36
38
|
|
37
39
|
class << self
|
38
|
-
def detect(
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
40
|
+
def detect(address_or_url)
|
41
|
+
address_or_url = "https://#{address_or_url}" unless address_or_url.match?(%r{^[a-z]{1,6}://})
|
42
|
+
urls = [address_or_url]
|
43
|
+
urls.push("#{address_or_url}#{STANDARD_PATH}") unless address_or_url.end_with?(STANDARD_PATH)
|
44
|
+
|
45
|
+
urls.each do |base_url|
|
46
|
+
next unless base_url.start_with?('https://')
|
47
|
+
api = Rest.new(base_url: base_url, redirect_max: 1)
|
48
|
+
result = api.call(
|
49
|
+
operation: 'POST',
|
50
|
+
subpath: '',
|
51
|
+
headers: {'Accept' => 'application/xrds+xml', 'Content-type' => 'text/plain'},
|
52
|
+
text_body_params: '')
|
53
|
+
# 4.x
|
54
|
+
next unless result[:http].body.start_with?('<?xml')
|
47
55
|
res_s = XmlSimple.xml_in(result[:http].body, {'ForceArray' => false})
|
56
|
+
Log.log.debug{"version: #{result[:http]['X-IBM-Aspera']}"}
|
48
57
|
version = res_s['XRD']['application']['version']
|
49
|
-
|
58
|
+
# take redirect if any
|
59
|
+
return {version: version, url: result[:http].uri.to_s}
|
60
|
+
rescue StandardError => e
|
61
|
+
Log.log.debug{"detect error: #{e}"}
|
50
62
|
end
|
51
63
|
return nil
|
52
64
|
end
|
53
65
|
|
66
|
+
def wizard(object:, private_key_path: nil, pub_key_pem: nil)
|
67
|
+
options = object.options
|
68
|
+
return {
|
69
|
+
preset_value: {
|
70
|
+
url: options.get_option(:url, mandatory: true),
|
71
|
+
username: options.get_option(:username, mandatory: true),
|
72
|
+
password: options.get_option(:password, mandatory: true)
|
73
|
+
},
|
74
|
+
test_args: 'me'
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
54
78
|
# extract elements from anonymous faspex link
|
55
79
|
def get_link_data(public_url)
|
56
80
|
public_uri = URI.parse(public_url)
|
57
|
-
raise
|
81
|
+
raise Cli::BadArgument, 'Public link does not match Faspex format' unless (m = public_uri.path.match(%r{^(.*)/(external.*)$}))
|
58
82
|
base = m[1]
|
59
83
|
subpath = m[2]
|
60
84
|
port_add = public_uri.port.eql?(public_uri.default_port) ? '' : ":#{public_uri.port}"
|
61
85
|
result = {
|
62
86
|
base_url: "#{public_uri.scheme}://#{public_uri.host}#{port_add}#{base}",
|
63
87
|
subpath: subpath,
|
64
|
-
query:
|
88
|
+
query: Rest.decode_query(public_uri.query)
|
65
89
|
}
|
66
|
-
Log.dump('link data', result)
|
90
|
+
Log.log.debug{Log.dump('link data', result)}
|
67
91
|
return result
|
68
92
|
end
|
69
93
|
|
70
|
-
# get
|
94
|
+
# get Fasp::Uri::SCHEME URI from entry in xml, and fix problems..
|
71
95
|
def get_fasp_uri_from_entry(entry, raise_no_link: true)
|
72
96
|
unless entry.key?('link')
|
73
|
-
raise
|
97
|
+
raise Cli::BadArgument, 'package has no link (deleted?)' if raise_no_link
|
74
98
|
return nil
|
75
99
|
end
|
76
100
|
result = entry['link'].find{|e| e['rel'].eql?('package')}['href']
|
@@ -80,21 +104,11 @@ module Aspera
|
|
80
104
|
return result
|
81
105
|
end
|
82
106
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
# field_sym : :id or :name
|
92
|
-
def get_source_id(source_list, source_name)
|
93
|
-
source_ids = source_list.select { |i| i['name'].eql?(source_name) }
|
94
|
-
if source_ids.empty?
|
95
|
-
raise CliError, %Q(No such Faspex source "#{source_name}" in [#{source_list.map{|i| %Q("#{i['name']}")}.join(', ')}])
|
96
|
-
end
|
97
|
-
return source_ids.first['id']
|
107
|
+
# @return [Integer] identifier of source
|
108
|
+
def get_source_id_by_name(source_name, source_list)
|
109
|
+
match_source = source_list.find { |i| i['name'].eql?(source_name) }
|
110
|
+
return match_source['id'] unless match_source.nil?
|
111
|
+
raise Cli::Error, %Q(No such Faspex source: "#{source_name}" in [#{source_list.map{|i| %Q("#{i['name']}")}.join(', ')}])
|
98
112
|
end
|
99
113
|
end
|
100
114
|
|
@@ -104,8 +118,8 @@ module Aspera
|
|
104
118
|
super(env)
|
105
119
|
options.declare(:link, 'Public link for specific operation')
|
106
120
|
options.declare(:delivery_info, 'Package delivery information', types: Hash)
|
107
|
-
options.declare(:
|
108
|
-
options.declare(:storage, 'Faspex local storage definition')
|
121
|
+
options.declare(:remote_source, 'Remote source for package send (id or %name:)')
|
122
|
+
options.declare(:storage, 'Faspex local storage definition (for browsing source)')
|
109
123
|
options.declare(:recipient, 'Use if recipient is a dropbox (with *)')
|
110
124
|
options.declare(:box, 'Package box', values: ATOM_MAILBOXES, default: :inbox)
|
111
125
|
options.parse_options!
|
@@ -160,8 +174,8 @@ module Aspera
|
|
160
174
|
# get a batch of package information
|
161
175
|
# order: first batch is latest packages, and then in a batch ids are increasing
|
162
176
|
atom_xml = api_v3.call({operation: 'GET', subpath: "#{mailbox}.atom", headers: {'Accept' => 'application/xml'}, url_params: mailbox_query})[:http].body
|
163
|
-
box_data = XmlSimple.xml_in(atom_xml, {'ForceArray' =>
|
164
|
-
Log.dump(:box_data, box_data)
|
177
|
+
box_data = XmlSimple.xml_in(atom_xml, {'ForceArray' => %w[entry field link to]})
|
178
|
+
Log.log.debug{Log.dump(:box_data, box_data)}
|
165
179
|
items = box_data.key?('entry') ? box_data['entry'] : []
|
166
180
|
Log.log.debug{"new items: #{items.count}"}
|
167
181
|
# it is the end if page is empty
|
@@ -173,11 +187,14 @@ module Aspera
|
|
173
187
|
package[PACKAGE_MATCH_FIELD] =
|
174
188
|
case mailbox
|
175
189
|
when :inbox, :archive
|
176
|
-
recipient = package['to'].find{|i|recipient_names.include?(i['name']
|
177
|
-
recipient.nil? ? nil : recipient['recipient_delivery_id']
|
190
|
+
recipient = package['to'].find{|i|recipient_names.include?(i['name'])}
|
191
|
+
recipient.nil? ? nil : recipient['recipient_delivery_id']
|
178
192
|
else # :sent
|
179
|
-
package['delivery_id']
|
193
|
+
package['delivery_id']
|
180
194
|
end
|
195
|
+
# add special key
|
196
|
+
package['items'] = package['link'].is_a?(Array) ? package['link'].length : 0
|
197
|
+
package['metadata'] = package['metadata']['field'].each_with_object({}){|i, m| m[i['name']] = i['content'] }
|
181
198
|
# if we look for a specific package
|
182
199
|
stop_condition = true if !stop_at_id.nil? && stop_at_id.eql?(package[PACKAGE_MATCH_FIELD])
|
183
200
|
# keep only those for the specified recipient
|
@@ -197,7 +214,7 @@ module Aspera
|
|
197
214
|
break if link.nil?
|
198
215
|
# replace parameters with the ones from next link
|
199
216
|
params = CGI.parse(URI.parse(link['href']).query)
|
200
|
-
mailbox_query = params.keys.each_with_object({}){|i, m
|
217
|
+
mailbox_query = params.keys.each_with_object({}){|i, m| m[i] = params[i].first }
|
201
218
|
Log.log.debug{"query: #{mailbox_query}"}
|
202
219
|
break if !max_pages.nil? && (mailbox_query['page'].to_i > max_pages)
|
203
220
|
end
|
@@ -210,7 +227,7 @@ module Aspera
|
|
210
227
|
# pub link user
|
211
228
|
link_data = self.class.get_link_data(public_link_url)
|
212
229
|
if !['external/submissions/new', 'external/dropbox_submissions/new'].include?(link_data[:subpath])
|
213
|
-
raise
|
230
|
+
raise Cli::BadArgument, "pub link is #{link_data[:subpath]}, expecting external/submissions/new"
|
214
231
|
end
|
215
232
|
create_path = link_data[:subpath].split('/')[0..-2].join('/')
|
216
233
|
package_create_params[:passcode] = link_data[:query]['passcode']
|
@@ -225,11 +242,11 @@ module Aspera
|
|
225
242
|
subpath: create_path,
|
226
243
|
json_params: package_create_params,
|
227
244
|
headers: {'Accept' => 'text/javascript'}})[:http].body
|
228
|
-
# get
|
245
|
+
# get arguments of function call
|
229
246
|
package_creation_data.delete!("\n") # one line
|
230
247
|
package_creation_data.gsub!(/^[^"]+\("\{/, '{') # delete header
|
231
248
|
package_creation_data.gsub!(/"\);[^"]+$/, '"') # delete trailer
|
232
|
-
package_creation_data.gsub!(/\}", *"/, '},"') # between two
|
249
|
+
package_creation_data.gsub!(/\}", *"/, '},"') # between two arguments
|
233
250
|
package_creation_data.gsub!('\\"', '"') # remove protecting quote
|
234
251
|
begin
|
235
252
|
package_creation_data = JSON.parse("[#{package_creation_data}]")
|
@@ -254,18 +271,20 @@ module Aspera
|
|
254
271
|
end
|
255
272
|
return nagios.result
|
256
273
|
when :package
|
257
|
-
command_pkg = options.get_next_command(%i[send recv list])
|
274
|
+
command_pkg = options.get_next_command(%i[send recv list show])
|
258
275
|
case command_pkg
|
276
|
+
when :show
|
277
|
+
delivery_id = instance_identifier
|
278
|
+
return {type: :single_object, data: mailbox_filtered_entries(stop_at_id: delivery_id).find{|p|p[PACKAGE_MATCH_FIELD].eql?(delivery_id)} }
|
259
279
|
when :list
|
260
280
|
return {
|
261
|
-
type:
|
262
|
-
data:
|
263
|
-
fields:
|
264
|
-
textify: lambda {|table_data|Faspex.textify_package_list(table_data)}
|
281
|
+
type: :object_list,
|
282
|
+
data: mailbox_filtered_entries,
|
283
|
+
fields: [PACKAGE_MATCH_FIELD, 'title', 'items']
|
265
284
|
}
|
266
285
|
when :send
|
267
286
|
delivery_info = options.get_option(:delivery_info, mandatory: true)
|
268
|
-
raise
|
287
|
+
raise Cli::BadArgument, 'delivery_info must be hash, refer to doc' unless delivery_info.is_a?(Hash)
|
269
288
|
# actual parameter to faspex API
|
270
289
|
package_create_params = {'delivery' => delivery_info}
|
271
290
|
public_link_url = options.get_option(:link)
|
@@ -274,30 +293,30 @@ module Aspera
|
|
274
293
|
delivery_info['sources'] ||= [{'paths' => []}]
|
275
294
|
first_source = delivery_info['sources'].first
|
276
295
|
first_source['paths'].push(*transfer.source_list)
|
277
|
-
|
278
|
-
|
296
|
+
source_id = instance_identifier(as_option: :remote_source) do |field, value|
|
297
|
+
raise Cli::BadArgument, 'only name as selector, or give id' unless field.eql?('name')
|
279
298
|
source_list = api_v3.call({operation: 'GET', subpath: 'source_shares', headers: {'Accept' => 'application/json'}})[:data]['items']
|
280
|
-
|
281
|
-
first_source['id'] = source_id
|
299
|
+
self.class.get_source_id_by_name(value, source_list)
|
282
300
|
end
|
301
|
+
first_source['id'] = source_id.to_i unless source_id.nil?
|
283
302
|
pkg_created = api_v3.call({
|
284
303
|
operation: 'POST',
|
285
304
|
subpath: 'send',
|
286
305
|
json_params: package_create_params,
|
287
306
|
headers: {'Accept' => 'application/json'}
|
288
307
|
})[:data]
|
289
|
-
if
|
290
|
-
# no transfer spec if remote source
|
308
|
+
if first_source.key?('id')
|
309
|
+
# no transfer spec if remote source: handled by faspex
|
291
310
|
return {data: [pkg_created['links']['status']], type: :value_list, name: 'link'}
|
292
311
|
end
|
293
|
-
raise
|
312
|
+
raise Cli::BadArgument, 'expecting one session exactly' if pkg_created['xfer_sessions'].length != 1
|
294
313
|
transfer_spec = pkg_created['xfer_sessions'].first
|
295
314
|
# use source from cmd line, this one only contains destination (already in dest root)
|
296
315
|
transfer_spec.delete('paths')
|
297
316
|
else # public link
|
298
317
|
transfer_spec = send_public_link_to_ts(public_link_url, package_create_params)
|
299
318
|
end
|
300
|
-
# Log.dump('transfer_spec',transfer_spec)
|
319
|
+
# Log.log.debug{Log.dump('transfer_spec',transfer_spec)}
|
301
320
|
return Main.result_transfer(transfer.start(transfer_spec))
|
302
321
|
when :recv
|
303
322
|
link_url = options.get_option(:link)
|
@@ -322,11 +341,11 @@ module Aspera
|
|
322
341
|
delivery_id = instance_identifier
|
323
342
|
raise 'empty id' if delivery_id.empty?
|
324
343
|
recipient = options.get_option(:recipient)
|
325
|
-
if
|
344
|
+
if ExtendedValue::ALL.eql?(delivery_id)
|
326
345
|
pkg_id_uri = mailbox_filtered_entries.map{|i|{id: i[PACKAGE_MATCH_FIELD], uri: self.class.get_fasp_uri_from_entry(i, raise_no_link: false)}}
|
327
346
|
elsif !recipient.nil? && recipient.start_with?('*')
|
328
347
|
found_package_link = mailbox_filtered_entries(stop_at_id: delivery_id).find{|p|p[PACKAGE_MATCH_FIELD].eql?(delivery_id)}['link'].first['href']
|
329
|
-
raise
|
348
|
+
raise "Not Found. Dropbox and Workgroup packages can use the link option with #{Fasp::Uri::SCHEME}" if found_package_link.nil?
|
330
349
|
pkg_id_uri = [{id: delivery_id, uri: found_package_link}]
|
331
350
|
else
|
332
351
|
# TODO: delivery id is the right one if package was receive by workgroup
|
@@ -339,12 +358,12 @@ module Aspera
|
|
339
358
|
package_entry = XmlSimple.xml_in(entry_xml, {'ForceArray' => true})
|
340
359
|
pkg_id_uri = [{id: delivery_id, uri: self.class.get_fasp_uri_from_entry(package_entry)}]
|
341
360
|
end
|
342
|
-
when
|
361
|
+
when /^#{Fasp::Uri::SCHEME}:/o
|
343
362
|
pkg_id_uri = [{id: 'package', uri: link_url}]
|
344
363
|
else
|
345
364
|
link_data = self.class.get_link_data(link_url)
|
346
365
|
if !link_data[:subpath].start_with?(PUB_LINK_EXTERNAL_MATCH)
|
347
|
-
raise
|
366
|
+
raise Cli::BadArgument, "Pub link is #{link_data[:subpath]}. Expecting #{PUB_LINK_EXTERNAL_MATCH}"
|
348
367
|
end
|
349
368
|
# NOTE: unauthenticated API (authorization is in url params)
|
350
369
|
api_public_link = Rest.new({base_url: link_data[:base_url]})
|
@@ -355,10 +374,10 @@ module Aspera
|
|
355
374
|
headers: {'Accept' => 'application/xml'})
|
356
375
|
if !package_creation_data[:http].body.start_with?('<?xml ')
|
357
376
|
OpenApplication.instance.uri(link_url)
|
358
|
-
raise
|
377
|
+
raise Cli::Error, 'Unexpected response: package not found ?'
|
359
378
|
end
|
360
379
|
package_entry = XmlSimple.xml_in(package_creation_data[:http].body, {'ForceArray' => false})
|
361
|
-
Log.dump(:package_entry, package_entry)
|
380
|
+
Log.log.debug{Log.dump(:package_entry, package_entry)}
|
362
381
|
transfer_uri = self.class.get_fasp_uri_from_entry(package_entry)
|
363
382
|
pkg_id_uri = [{id: package_entry['id'], uri: transfer_uri}]
|
364
383
|
end # public link
|
@@ -366,7 +385,7 @@ module Aspera
|
|
366
385
|
# TODO : remove ids from skip not present in inbox to avoid growing too big
|
367
386
|
# skip_ids_data.select!{|id|pkg_id_uri.select{|p|p[:id].eql?(id)}}
|
368
387
|
pkg_id_uri.reject!{|i|skip_ids_data.include?(i[:id])}
|
369
|
-
Log.dump(:pkg_id_uri, pkg_id_uri)
|
388
|
+
Log.log.debug{Log.dump(:pkg_id_uri, pkg_id_uri)}
|
370
389
|
return Main.result_status('no new package') if pkg_id_uri.empty?
|
371
390
|
result_transfer = []
|
372
391
|
pkg_id_uri.each do |id_uri|
|
@@ -375,7 +394,7 @@ module Aspera
|
|
375
394
|
statuses = [:success]
|
376
395
|
else
|
377
396
|
transfer_spec = Fasp::Uri.new(id_uri[:uri]).transfer_spec
|
378
|
-
# NOTE: only external users have token in
|
397
|
+
# NOTE: only external users have token in Fasp::Uri::SCHEME link !
|
379
398
|
if !transfer_spec.key?('token')
|
380
399
|
sanitized = id_uri[:uri].gsub('&', '&')
|
381
400
|
xml_payload =
|
@@ -397,41 +416,37 @@ module Aspera
|
|
397
416
|
return Main.result_transfer_multiple(result_transfer)
|
398
417
|
end
|
399
418
|
when :source
|
400
|
-
command_source = options.get_next_command(%i[list
|
419
|
+
command_source = options.get_next_command(%i[list info node])
|
401
420
|
source_list = api_v3.call({operation: 'GET', subpath: 'source_shares', headers: {'Accept' => 'application/json'}})[:data]['items']
|
402
421
|
case command_source
|
403
422
|
when :list
|
404
423
|
return {type: :object_list, data: source_list}
|
405
|
-
else # :
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
# get id and name
|
412
|
-
source_name = source_ids.first['name']
|
413
|
-
# source_id=source_ids.first['id']
|
424
|
+
else # :info :node
|
425
|
+
source_id = instance_identifier do |field, value|
|
426
|
+
raise Cli::BadArgument, 'only name as selector, or give id' unless field.eql?('name')
|
427
|
+
self.class.get_source_id_by_name(value, source_list)
|
428
|
+
end.to_i
|
429
|
+
source_name = source_list.find{|i|i['id'].eql?(source_id)}['name']
|
414
430
|
source_hash = options.get_option(:storage, mandatory: true)
|
415
431
|
# check value of option
|
416
|
-
raise
|
432
|
+
raise Cli::Error, 'storage option must be a Hash' unless source_hash.is_a?(Hash)
|
417
433
|
source_hash.each do |name, storage|
|
418
|
-
raise
|
434
|
+
raise Cli::Error, "storage '#{name}' must be a Hash" unless storage.is_a?(Hash)
|
419
435
|
[KEY_NODE, KEY_PATH].each do |key|
|
420
|
-
raise
|
436
|
+
raise Cli::Error, "storage '#{name}' must have a '#{key}'" unless storage.key?(key)
|
421
437
|
end
|
422
438
|
end
|
423
439
|
if !source_hash.key?(source_name)
|
424
|
-
raise
|
440
|
+
raise Cli::Error, "No such storage in config file: \"#{source_name}\" in [#{source_hash.keys.join(', ')}]"
|
425
441
|
end
|
426
442
|
source_info = source_hash[source_name]
|
427
|
-
Log.log.debug{
|
428
|
-
|
429
|
-
case command_node
|
443
|
+
Log.log.debug{Log.dump(:source_info, source_info)}
|
444
|
+
case command_source
|
430
445
|
when :info
|
431
446
|
return {data: source_info, type: :single_object}
|
432
447
|
when :node
|
433
448
|
node_config = ExtendedValue.instance.evaluate(source_info[KEY_NODE])
|
434
|
-
raise
|
449
|
+
raise Cli::Error, "bad type for: \"#{source_info[KEY_NODE]}\"" unless node_config.is_a?(Hash)
|
435
450
|
Log.log.debug{"node=#{node_config}"}
|
436
451
|
api_node = Rest.new({
|
437
452
|
base_url: node_config['url'],
|
@@ -440,7 +455,7 @@ module Aspera
|
|
440
455
|
username: node_config['username'],
|
441
456
|
password: node_config['password']}})
|
442
457
|
command = options.get_next_command(Node::COMMANDS_FASPEX)
|
443
|
-
return Node.new(@agents
|
458
|
+
return Node.new(@agents, api: api_node).execute_action(command, source_info[KEY_PATH])
|
444
459
|
end
|
445
460
|
end
|
446
461
|
when :me
|