aspera-cli 4.14.0 → 4.15.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 +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
|