aspera-cli 4.2.0 → 4.4.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
- data/README.md +749 -353
- data/docs/Makefile +4 -4
- data/docs/README.erb.md +743 -283
- data/docs/doc_tools.rb +58 -0
- data/docs/test_env.conf +9 -1
- data/examples/aoc.rb +14 -3
- data/examples/faspex4.rb +89 -0
- data/lib/aspera/aoc.rb +24 -22
- data/lib/aspera/cli/main.rb +48 -20
- data/lib/aspera/cli/plugin.rb +13 -6
- data/lib/aspera/cli/plugins/aoc.rb +117 -78
- data/lib/aspera/cli/plugins/config.rb +127 -80
- data/lib/aspera/cli/plugins/faspex.rb +112 -63
- data/lib/aspera/cli/plugins/faspex5.rb +29 -25
- data/lib/aspera/cli/plugins/node.rb +54 -25
- data/lib/aspera/cli/plugins/preview.rb +94 -68
- data/lib/aspera/cli/plugins/server.rb +16 -5
- data/lib/aspera/cli/transfer_agent.rb +92 -72
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/command_line_builder.rb +48 -31
- data/lib/aspera/cos_node.rb +4 -3
- data/lib/aspera/fasp/http_gw.rb +47 -26
- data/lib/aspera/fasp/local.rb +31 -24
- data/lib/aspera/fasp/manager.rb +3 -0
- data/lib/aspera/fasp/node.rb +23 -1
- data/lib/aspera/fasp/parameters.rb +72 -89
- data/lib/aspera/fasp/parameters.yaml +531 -0
- data/lib/aspera/fasp/uri.rb +1 -1
- data/lib/aspera/faspex_gw.rb +10 -9
- data/lib/aspera/id_generator.rb +22 -0
- data/lib/aspera/node.rb +11 -3
- data/lib/aspera/oauth.rb +131 -135
- data/lib/aspera/persistency_action_once.rb +11 -7
- data/lib/aspera/persistency_folder.rb +6 -26
- data/lib/aspera/rest.rb +1 -1
- data/lib/aspera/sync.rb +40 -35
- data/lib/aspera/timer_limiter.rb +22 -0
- data/lib/aspera/web_auth.rb +105 -0
- metadata +22 -4
- data/docs/transfer_spec.html +0 -99
- data/lib/aspera/fasp/aoc.rb +0 -24
|
@@ -7,8 +7,10 @@ require 'aspera/persistency_action_once'
|
|
|
7
7
|
require 'aspera/open_application'
|
|
8
8
|
require 'aspera/fasp/uri'
|
|
9
9
|
require 'aspera/nagios'
|
|
10
|
+
require 'aspera/id_generator'
|
|
10
11
|
require 'xmlsimple'
|
|
11
12
|
require 'json'
|
|
13
|
+
require 'cgi'
|
|
12
14
|
|
|
13
15
|
module Aspera
|
|
14
16
|
module Cli
|
|
@@ -17,7 +19,19 @@ module Aspera
|
|
|
17
19
|
KEY_NODE='node'
|
|
18
20
|
KEY_PATH='path'
|
|
19
21
|
VAL_ALL='ALL'
|
|
20
|
-
|
|
22
|
+
# added field in result that identifies the package
|
|
23
|
+
PACKAGE_MATCH_FIELD='package_id'
|
|
24
|
+
# list of supported atoms
|
|
25
|
+
ATOM_MAILBOXES=[:inbox, :archive, :sent]
|
|
26
|
+
# allowed parameters for inbox.atom
|
|
27
|
+
ATOM_PARAMS=['page', 'count', 'startIndex']
|
|
28
|
+
# with special parameters (from Plugin class)
|
|
29
|
+
ATOM_EXT_PARAMS=ATOM_PARAMS+[MAX_ITEMS, MAX_PAGES]
|
|
30
|
+
# sub path in url for public link delivery
|
|
31
|
+
PUB_LINK_EXTERNAL_MATCH='external_deliveries/'
|
|
32
|
+
private_constant :KEY_NODE,:KEY_PATH,:VAL_ALL,:PACKAGE_MATCH_FIELD,:ATOM_MAILBOXES,
|
|
33
|
+
:ATOM_PARAMS,:ATOM_EXT_PARAMS,:PUB_LINK_EXTERNAL_MATCH
|
|
34
|
+
|
|
21
35
|
def initialize(env)
|
|
22
36
|
@api_v3=nil
|
|
23
37
|
@api_v4=nil
|
|
@@ -26,7 +40,8 @@ module Aspera
|
|
|
26
40
|
self.options.add_opt_simple(:delivery_info,'package delivery information (extended value)')
|
|
27
41
|
self.options.add_opt_simple(:source_name,'create package from remote source (by name)')
|
|
28
42
|
self.options.add_opt_simple(:storage,'Faspex local storage definition')
|
|
29
|
-
self.options.
|
|
43
|
+
self.options.add_opt_simple(:recipient,'use if recipient is a dropbox (with *)')
|
|
44
|
+
self.options.add_opt_list(:box,ATOM_MAILBOXES,'package box')
|
|
30
45
|
self.options.set_option(:box,:inbox)
|
|
31
46
|
self.options.parse_options!
|
|
32
47
|
end
|
|
@@ -101,29 +116,57 @@ module Aspera
|
|
|
101
116
|
return @api_v4
|
|
102
117
|
end
|
|
103
118
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
# we match recv command on atom feed on this field
|
|
107
|
-
PACKAGE_MATCH_FIELD='package_id'
|
|
108
|
-
|
|
119
|
+
# query supports : {"startIndex":10,"count":1,"page":109}
|
|
109
120
|
def mailbox_all_entries
|
|
110
|
-
|
|
121
|
+
recipient_name=self.options.get_option(:recipient,:optional) || self.options.get_option(:username,:mandatory)
|
|
122
|
+
# mailbox is in ATOM_MAILBOXES
|
|
111
123
|
mailbox=self.options.get_option(:box,:mandatory)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
result
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
124
|
+
# parameters
|
|
125
|
+
mailbox_query=self.options.get_option(:query,:optional)
|
|
126
|
+
max_items=nil
|
|
127
|
+
max_pages=nil
|
|
128
|
+
result=[]
|
|
129
|
+
if !mailbox_query.nil?
|
|
130
|
+
raise "query: must be Hash or nil" unless mailbox_query.is_a?(Hash)
|
|
131
|
+
raise "query: supported params: #{ATOM_EXT_PARAMS}" unless (mailbox_query.keys-ATOM_EXT_PARAMS).empty?
|
|
132
|
+
raise "query: startIndex and page are exclusive" if mailbox_query.has_key?('startIndex') and mailbox_query.has_key?('page')
|
|
133
|
+
max_items=mailbox_query[MAX_ITEMS]
|
|
134
|
+
mailbox_query.delete(MAX_ITEMS)
|
|
135
|
+
max_pages=mailbox_query[MAX_PAGES]
|
|
136
|
+
mailbox_query.delete(MAX_PAGES)
|
|
137
|
+
end
|
|
138
|
+
loop do
|
|
139
|
+
atom_xml=api_v3.call({operation: 'GET',subpath: "#{mailbox}.atom",headers: {'Accept'=>'application/xml'},url_params: mailbox_query})[:http].body
|
|
140
|
+
box_data=XmlSimple.xml_in(atom_xml, {'ForceArray' => true})
|
|
141
|
+
Log.dump(:box_data,box_data)
|
|
142
|
+
items=box_data.has_key?('entry') ? box_data['entry'] : []
|
|
143
|
+
Log.log.debug("new items: #{items.count}")
|
|
144
|
+
# it is the end if page is empty
|
|
145
|
+
break if items.empty?
|
|
146
|
+
items.each do |package|
|
|
147
|
+
package[PACKAGE_MATCH_FIELD]=case mailbox
|
|
148
|
+
when :inbox,:archive
|
|
149
|
+
recipient=package['to'].select{|i|i['name'].first.eql?(recipient_name)}.first
|
|
150
|
+
recipient.nil? ? nil : recipient['recipient_delivery_id'].first
|
|
151
|
+
else # :sent
|
|
152
|
+
package['delivery_id'].first
|
|
153
|
+
end
|
|
154
|
+
# keep only those for the specified recipient
|
|
155
|
+
result.push(package) unless package[PACKAGE_MATCH_FIELD].nil?
|
|
123
156
|
end
|
|
157
|
+
Log.log.debug("total items: #{result.count}")
|
|
158
|
+
# reach the limit ?
|
|
159
|
+
break if !max_items.nil? and result.count > max_items
|
|
160
|
+
link=box_data['link'].select{|i|i['rel'].eql?('next')}.first
|
|
161
|
+
Log.log.debug("link: #{link}")
|
|
162
|
+
# no next link
|
|
163
|
+
break if link.nil?
|
|
164
|
+
# replace parameters with the ones from next link
|
|
165
|
+
params=CGI.parse(URI.parse(link['href']).query)
|
|
166
|
+
mailbox_query=params.keys.inject({}){|m,i|;m[i]=params[i].first;m}
|
|
167
|
+
Log.log.debug("query: #{mailbox_query}")
|
|
168
|
+
break if !max_pages.nil? and mailbox_query['page'].to_i > max_pages
|
|
124
169
|
end
|
|
125
|
-
# remove dropbox packages
|
|
126
|
-
result.select!{|p|p['metadata'].first['field'].select{|j|j['name'].eql?('_dropbox_name')}.empty? rescue false}
|
|
127
170
|
return result
|
|
128
171
|
end
|
|
129
172
|
|
|
@@ -159,6 +202,8 @@ module Aspera
|
|
|
159
202
|
return pkgdatares.first
|
|
160
203
|
end
|
|
161
204
|
|
|
205
|
+
ACTIONS=[ :health,:package, :source, :me, :dropbox, :v4, :address_book, :login_methods ]
|
|
206
|
+
|
|
162
207
|
def execute_action
|
|
163
208
|
command=self.options.get_next_command(ACTIONS)
|
|
164
209
|
case command
|
|
@@ -208,52 +253,59 @@ module Aspera
|
|
|
208
253
|
#Log.dump('transfer_spec',transfer_spec)
|
|
209
254
|
return Main.result_transfer(self.transfer.start(transfer_spec,{:src=>:node_gen3}))
|
|
210
255
|
when :recv
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
256
|
+
link_url=self.options.get_option(:link,:optional)
|
|
257
|
+
# list of faspex ID/URI to download
|
|
258
|
+
pkg_id_uri=nil
|
|
259
|
+
skip_ids_data=[]
|
|
260
|
+
skip_ids_persistency=nil
|
|
261
|
+
case link_url
|
|
262
|
+
when nil # usual case: no link
|
|
263
|
+
if self.options.get_option(:once_only,:mandatory)
|
|
264
|
+
skip_ids_persistency=PersistencyActionOnce.new(
|
|
265
|
+
manager: @agents[:persistency],
|
|
266
|
+
data: skip_ids_data,
|
|
267
|
+
id: IdGenerator.from_list(['faspex_recv',self.options.get_option(:url,:mandatory),self.options.get_option(:username,:mandatory),self.options.get_option(:box,:mandatory).to_s]))
|
|
268
|
+
end
|
|
269
|
+
# get command line parameters
|
|
270
|
+
delivid=self.options.get_option(:id,:mandatory)
|
|
271
|
+
if delivid.eql?(VAL_ALL)
|
|
272
|
+
pkg_id_uri=mailbox_all_entries.map{|i|{:id=>i[PACKAGE_MATCH_FIELD],:uri=>self.class.get_fasp_uri_from_entry(i)}}
|
|
273
|
+
# TODO : remove ids from skip not present in inbox
|
|
274
|
+
# skip_ids_data.select!{|id|pkg_id_uri.select{|p|p[:id].eql?(id)}}
|
|
275
|
+
pkg_id_uri.select!{|i|!skip_ids_data.include?(i[:id])}
|
|
276
|
+
else
|
|
277
|
+
recipient=options.get_option(:recipient,:optional)
|
|
278
|
+
if !recipient.nil? and recipient.start_with?('*')
|
|
279
|
+
raise "Dropbox and Workgroup packages should use link option with faspe:"
|
|
280
|
+
end
|
|
281
|
+
# TODO: delivery id is the right one if package was receive by workgroup
|
|
282
|
+
endpoint=case self.options.get_option(:box,:mandatory)
|
|
283
|
+
when :inbox,:archive;'received'
|
|
284
|
+
when :sent; 'sent'
|
|
285
|
+
end
|
|
286
|
+
entry_xml=api_v3.call({:operation=>'GET',:subpath=>"#{endpoint}/#{delivid}",:headers=>{'Accept'=>'application/xml'}})[:http].body
|
|
287
|
+
package_entry=XmlSimple.xml_in(entry_xml, {'ForceArray' => true})
|
|
288
|
+
pkg_id_uri=[{:id=>delivid,:uri=>self.class.get_fasp_uri_from_entry(package_entry)}]
|
|
289
|
+
end
|
|
290
|
+
when /^faspe:/
|
|
291
|
+
pkg_id_uri=[{:id=>'package',:uri=>link_url}]
|
|
292
|
+
else
|
|
293
|
+
link_data=self.class.get_link_data(link_url)
|
|
294
|
+
if !link_data[:subpath].start_with?(PUB_LINK_EXTERNAL_MATCH)
|
|
295
|
+
raise CliBadArgument,"Pub link is #{link_data[:subpath]}. Expecting #{PUB_LINK_EXTERNAL_MATCH}"
|
|
216
296
|
end
|
|
217
|
-
# Note: unauthenticated API
|
|
297
|
+
# Note: unauthenticated API (autorization is in url params)
|
|
218
298
|
api_public_link=Rest.new({:base_url=>link_data[:base_url]})
|
|
219
299
|
pkgdatares=api_public_link.call({:operation=>'GET',:subpath=>link_data[:subpath],:url_params=>{:passcode=>link_data[:query]['passcode']},:headers=>{'Accept'=>'application/xml'}})
|
|
220
300
|
if !pkgdatares[:http].body.start_with?('<?xml ')
|
|
221
|
-
OpenApplication.instance.uri(
|
|
301
|
+
OpenApplication.instance.uri(link_url)
|
|
222
302
|
raise CliError, 'no such package'
|
|
223
303
|
end
|
|
224
304
|
package_entry=XmlSimple.xml_in(pkgdatares[:http].body, {'ForceArray' => false})
|
|
305
|
+
Log.dump(:package_entry,package_entry)
|
|
225
306
|
transfer_uri=self.class.get_fasp_uri_from_entry(package_entry)
|
|
226
|
-
|
|
227
|
-
transfer_spec['direction']='receive'
|
|
228
|
-
return Main.result_transfer(self.transfer.start(transfer_spec,{:src=>:node_gen3}))
|
|
307
|
+
pkg_id_uri=[{:id=>package_entry['id'],:uri=>transfer_uri}]
|
|
229
308
|
end # public link
|
|
230
|
-
# get command line parameters
|
|
231
|
-
delivid=self.options.get_option(:id,:mandatory)
|
|
232
|
-
# list of faspex ID/URI to download
|
|
233
|
-
pkg_id_uri=nil
|
|
234
|
-
skip_ids_data=[]
|
|
235
|
-
skip_ids_persistency=nil
|
|
236
|
-
if self.options.get_option(:once_only,:mandatory)
|
|
237
|
-
skip_ids_persistency=PersistencyActionOnce.new(
|
|
238
|
-
manager: @agents[:persistency],
|
|
239
|
-
data: skip_ids_data,
|
|
240
|
-
ids: ['faspex_recv',self.options.get_option(:url,:mandatory),self.options.get_option(:username,:mandatory),self.options.get_option(:box,:mandatory).to_s])
|
|
241
|
-
end
|
|
242
|
-
if delivid.eql?(VAL_ALL)
|
|
243
|
-
pkg_id_uri=mailbox_all_entries.map{|i|{:id=>i[PACKAGE_MATCH_FIELD],:uri=>self.class.get_fasp_uri_from_entry(i)}}
|
|
244
|
-
# TODO : remove ids from skip not present in inbox
|
|
245
|
-
# skip_ids_data.select!{|id|pkg_id_uri.select{|p|p[:id].eql?(id)}}
|
|
246
|
-
pkg_id_uri.select!{|i|!skip_ids_data.include?(i[:id])}
|
|
247
|
-
else
|
|
248
|
-
# TODO: delivery id is the right one if package was receive by group
|
|
249
|
-
endpoint=case self.options.get_option(:box,:mandatory)
|
|
250
|
-
when :inbox,:archive;'received'
|
|
251
|
-
when :sent; 'sent'
|
|
252
|
-
end
|
|
253
|
-
entry_xml=api_v3.call({:operation=>'GET',:subpath=>"#{endpoint}/#{delivid}",:headers=>{'Accept'=>'application/xml'}})[:http].body
|
|
254
|
-
package_entry=XmlSimple.xml_in(entry_xml, {'ForceArray' => true})
|
|
255
|
-
pkg_id_uri=[{:id=>delivid,:uri=>self.class.get_fasp_uri_from_entry(package_entry)}]
|
|
256
|
-
end
|
|
257
309
|
Log.dump(:pkg_id_uri,pkg_id_uri)
|
|
258
310
|
return Main.result_status('no package') if pkg_id_uri.empty?
|
|
259
311
|
result_transfer=[]
|
|
@@ -262,20 +314,17 @@ module Aspera
|
|
|
262
314
|
# NOTE: only external users have token in faspe: link !
|
|
263
315
|
if !transfer_spec.has_key?('token')
|
|
264
316
|
sanitized=id_uri[:uri].gsub('&','&')
|
|
265
|
-
# TODO: file jira
|
|
266
|
-
#XXsanitized.gsub!(/%3D%3D$/,'==')
|
|
267
|
-
#XXsanitized.gsub!(/%3D$/,'=')
|
|
268
317
|
xmlpayload='<?xml version="1.0" encoding="UTF-8"?><url-list xmlns="http://schemas.asperasoft.com/xml/url-list"><url href="'+sanitized+'"/></url-list>'
|
|
269
318
|
transfer_spec['token']=api_v3.call({:operation=>'POST',:subpath=>'issue-token?direction=down',:headers=>{'Accept'=>'text/plain','Content-Type'=>'application/vnd.aspera.url-list+xml'},:text_body_params=>xmlpayload})[:http].body
|
|
270
319
|
end
|
|
271
320
|
transfer_spec['direction']='receive'
|
|
272
321
|
statuses=self.transfer.start(transfer_spec,{:src=>:node_gen3})
|
|
273
|
-
result_transfer.push({'package'=>id_uri[:id],
|
|
322
|
+
result_transfer.push({'package'=>id_uri[:id],Main::STATUS_FIELD=>statuses})
|
|
274
323
|
# skip only if all sessions completed
|
|
275
324
|
skip_ids_data.push(id_uri[:id]) if TransferAgent.session_status(statuses).eql?(:success)
|
|
276
325
|
end
|
|
277
326
|
skip_ids_persistency.save unless skip_ids_persistency.nil?
|
|
278
|
-
return
|
|
327
|
+
return Main.result_transfer_multiple(result_transfer)
|
|
279
328
|
end
|
|
280
329
|
when :source
|
|
281
330
|
command_source=self.options.get_next_command([ :list, :id, :name ])
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'aspera/cli/basic_auth_plugin'
|
|
2
2
|
require 'aspera/persistency_action_once'
|
|
3
|
+
require 'aspera/id_generator'
|
|
3
4
|
require 'securerandom'
|
|
4
5
|
|
|
5
6
|
module Aspera
|
|
@@ -17,14 +18,20 @@ module Aspera
|
|
|
17
18
|
options.set_option(:auth,:jwt)
|
|
18
19
|
options.parse_options!
|
|
19
20
|
end
|
|
20
|
-
ACTIONS=[ :node, :package, :auth_client ]
|
|
21
21
|
|
|
22
22
|
def set_api
|
|
23
|
-
faxpex5_api_base_url=options.get_option(:url,:mandatory)
|
|
24
|
-
faxpex5_api_v5_url="#{faxpex5_api_base_url}/api/v5"
|
|
25
|
-
faxpex5_api_auth_url="#{faxpex5_api_base_url}/auth"
|
|
23
|
+
@faxpex5_api_base_url=options.get_option(:url,:mandatory)
|
|
24
|
+
faxpex5_api_v5_url="#{@faxpex5_api_base_url}/api/v5"
|
|
25
|
+
faxpex5_api_auth_url="#{@faxpex5_api_base_url}/auth"
|
|
26
26
|
case options.get_option(:auth,:mandatory)
|
|
27
|
+
when :boot
|
|
28
|
+
# the password here is the token copied directly from browser in developer mode
|
|
29
|
+
@api_v5=Rest.new({
|
|
30
|
+
:base_url => faxpex5_api_v5_url,
|
|
31
|
+
:headers => {'Authorization'=>options.get_option(:password,:mandatory)},
|
|
32
|
+
})
|
|
27
33
|
when :web
|
|
34
|
+
# opens a browser and ask user to auth using web
|
|
28
35
|
@api_v5=Rest.new({
|
|
29
36
|
:base_url => faxpex5_api_v5_url,
|
|
30
37
|
:auth => {
|
|
@@ -34,18 +41,9 @@ module Aspera
|
|
|
34
41
|
:state => SecureRandom.uuid,
|
|
35
42
|
:client_id => options.get_option(:client_id,:mandatory),
|
|
36
43
|
:redirect_uri => options.get_option(:redirect_uri,:mandatory),
|
|
37
|
-
#:token_field =>'auth_token',
|
|
38
|
-
#:path_token => 'token',
|
|
39
|
-
#:path_authorize => 'authorize',
|
|
40
|
-
#:userpass_body => {name: faxpex5_username,password: faxpex5_password}
|
|
41
44
|
}})
|
|
42
|
-
when :boot
|
|
43
|
-
@api_v5=Rest.new({
|
|
44
|
-
:base_url => faxpex5_api_v5_url,
|
|
45
|
-
:headers => {'Authorization'=>options.get_option(:password,:mandatory)},
|
|
46
|
-
})
|
|
47
45
|
when :jwt
|
|
48
|
-
#
|
|
46
|
+
# currently Faspex 5 beta 3 only supports non-user based apis (e.g. jobs)
|
|
49
47
|
app_client_id=options.get_option(:client_id,:mandatory)
|
|
50
48
|
@api_v5=Rest.new({
|
|
51
49
|
:base_url => faxpex5_api_v5_url,
|
|
@@ -53,28 +51,33 @@ module Aspera
|
|
|
53
51
|
:type => :oauth2,
|
|
54
52
|
:base_url => faxpex5_api_auth_url,
|
|
55
53
|
:grant => :jwt,
|
|
54
|
+
:f5_username => options.get_option(:username,:mandatory),
|
|
55
|
+
:f5_password => options.get_option(:password,:mandatory),
|
|
56
56
|
:client_id => app_client_id,
|
|
57
57
|
:client_secret => options.get_option(:client_secret,:mandatory),
|
|
58
|
-
#:redirect_uri => options.get_option(:redirect_uri,:mandatory),
|
|
59
58
|
:jwt_subject => "client:#{app_client_id}", # TODO Mmmm
|
|
60
59
|
:jwt_audience => app_client_id, # TODO Mmmm
|
|
61
60
|
:jwt_private_key_obj => OpenSSL::PKey::RSA.new(options.get_option(:private_key,:mandatory)),
|
|
62
|
-
:jwt_is_f5 => true,
|
|
63
61
|
:jwt_headers => {typ: 'JWT'}
|
|
64
62
|
}})
|
|
65
63
|
end
|
|
66
64
|
end
|
|
67
65
|
|
|
66
|
+
ACTIONS=[ :node, :package, :auth_client, :jobs ]
|
|
67
|
+
|
|
68
68
|
#
|
|
69
69
|
def execute_action
|
|
70
70
|
set_api
|
|
71
71
|
command=options.get_next_command(ACTIONS)
|
|
72
72
|
case command
|
|
73
73
|
when :auth_client
|
|
74
|
-
api_auth=Rest.new(@api_v5.params.merge({base_url: @
|
|
74
|
+
api_auth=Rest.new(@api_v5.params.merge({base_url: "#{@faxpex5_api_base_url}/auth"}))
|
|
75
75
|
return self.entity_action(api_auth,'oauth_clients',nil,:id,nil,true)
|
|
76
76
|
when :node
|
|
77
77
|
return self.entity_action(@api_v5,'nodes',nil,:id,nil,true)
|
|
78
|
+
when :jobs
|
|
79
|
+
# to test JWT
|
|
80
|
+
return self.entity_action(@api_v5,'jobs',nil,:id,nil,true)
|
|
78
81
|
when :package
|
|
79
82
|
command=options.get_next_command([:list,:show,:send,:receive])
|
|
80
83
|
case command
|
|
@@ -86,7 +89,7 @@ module Aspera
|
|
|
86
89
|
return {:type => :single_object, :data=>@api_v5.read("packages/#{id}")[:data]}
|
|
87
90
|
when :send
|
|
88
91
|
parameters=options.get_option(:value,:mandatory)
|
|
89
|
-
raise CliBadArgument,'
|
|
92
|
+
raise CliBadArgument,'value must be hash, refer to API' unless parameters.is_a?(Hash)
|
|
90
93
|
package=@api_v5.create('packages',parameters)[:data]
|
|
91
94
|
transfer_spec=@api_v5.create("packages/#{package['id']}/transfer_spec/upload",{transfer_type: 'Connect'})[:data]
|
|
92
95
|
transfer_spec.delete('authentication')
|
|
@@ -98,16 +101,17 @@ module Aspera
|
|
|
98
101
|
skip_ids_data=[]
|
|
99
102
|
skip_ids_persistency=nil
|
|
100
103
|
if options.get_option(:once_only,:mandatory)
|
|
104
|
+
# read ids from persistency
|
|
101
105
|
skip_ids_persistency=PersistencyActionOnce.new(
|
|
102
106
|
manager: @agents[:persistency],
|
|
103
|
-
data:
|
|
104
|
-
|
|
107
|
+
data: skip_ids_data,
|
|
108
|
+
id: IdGenerator.from_list(['faspex_recv',options.get_option(:url,:mandatory),options.get_option(:username,:mandatory),pkg_type]))
|
|
105
109
|
end
|
|
106
110
|
if pack_id.eql?(VAL_ALL)
|
|
107
|
-
#
|
|
111
|
+
# TODO: if packages have same name, they will overwrite
|
|
108
112
|
parameters=options.get_option(:value,:optional)
|
|
109
|
-
parameters||={
|
|
110
|
-
raise CliBadArgument,'value filter must be
|
|
113
|
+
parameters||={'type'=>'received','subtype'=>'mypackages','limit'=>1000}
|
|
114
|
+
raise CliBadArgument,'value filter must be Hash (API GET)' unless parameters.is_a?(Hash)
|
|
111
115
|
package_ids=@api_v5.read('packages',parameters)[:data]['packages'].map{|p|p['id']}
|
|
112
116
|
package_ids.select!{|i|!skip_ids_data.include?(i)}
|
|
113
117
|
end
|
|
@@ -117,12 +121,12 @@ module Aspera
|
|
|
117
121
|
transfer_spec=@api_v5.create("packages/#{id}/transfer_spec/download",{transfer_type: 'Connect', type: pkg_type})[:data]
|
|
118
122
|
transfer_spec.delete('authentication')
|
|
119
123
|
statuses=self.transfer.start(transfer_spec,{:src=>:node_gen3})
|
|
120
|
-
result_transfer.push({'package'=>id,
|
|
124
|
+
result_transfer.push({'package'=>id,Main::STATUS_FIELD=>statuses})
|
|
121
125
|
# skip only if all sessions completed
|
|
122
126
|
skip_ids_data.push(id) if TransferAgent.session_status(statuses).eql?(:success)
|
|
123
127
|
end
|
|
124
128
|
skip_ids_persistency.save unless skip_ids_persistency.nil?
|
|
125
|
-
return
|
|
129
|
+
return Main.result_transfer_multiple(result_transfer)
|
|
126
130
|
end
|
|
127
131
|
end
|
|
128
132
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'aspera/cli/basic_auth_plugin'
|
|
2
2
|
require 'aspera/nagios'
|
|
3
3
|
require 'aspera/hash_ext'
|
|
4
|
+
require 'aspera/id_generator'
|
|
4
5
|
require 'base64'
|
|
5
6
|
require 'zlib'
|
|
6
7
|
|
|
@@ -12,22 +13,34 @@ module Aspera
|
|
|
12
13
|
private_constant :SAMPLE_SOAP_CALL
|
|
13
14
|
def initialize(env)
|
|
14
15
|
super(env)
|
|
15
|
-
# this is added to some requests , for instance to add tags
|
|
16
|
+
# this is added to some requests , for instance to add tags (COS)
|
|
16
17
|
@add_request_param = env[:add_request_param] || {}
|
|
17
18
|
unless env[:skip_basic_auth_options]
|
|
18
19
|
self.options.add_opt_simple(:validator,"identifier of validator (optional for central)")
|
|
19
20
|
self.options.add_opt_simple(:asperabrowserurl,"URL for simple aspera web ui")
|
|
20
21
|
self.options.add_opt_simple(:name,"sync name")
|
|
21
|
-
self.options.add_opt_list(:
|
|
22
|
+
self.options.add_opt_list(:token_type,[:aspera,:basic,:hybrid],'Type of token used for transfers')
|
|
22
23
|
self.options.set_option(:asperabrowserurl,'https://asperabrowser.mybluemix.net')
|
|
23
|
-
self.options.set_option(:
|
|
24
|
+
self.options.set_option(:token_type,:aspera)
|
|
24
25
|
self.options.parse_options!
|
|
25
26
|
end
|
|
26
27
|
return if env[:man_only]
|
|
27
28
|
if env.has_key?(:node_api)
|
|
28
29
|
@api_node=env[:node_api]
|
|
29
30
|
else
|
|
30
|
-
|
|
31
|
+
if self.options.get_option(:password,:mandatory).start_with?('Bearer ')
|
|
32
|
+
# info is provided like node_info of aoc
|
|
33
|
+
@api_node=Rest.new({
|
|
34
|
+
base_url: self.options.get_option(:url,:mandatory),
|
|
35
|
+
headers: {
|
|
36
|
+
'Authorization' => self.options.get_option(:password,:mandatory),
|
|
37
|
+
'X-Aspera-AccessKey' => self.options.get_option(:username,:mandatory),
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
else
|
|
41
|
+
# this is normal case
|
|
42
|
+
@api_node=basic_auth_api
|
|
43
|
+
end
|
|
31
44
|
end
|
|
32
45
|
end
|
|
33
46
|
|
|
@@ -190,22 +203,36 @@ module Aspera
|
|
|
190
203
|
#raise "unknown type: #{send_result['self']['type']}"
|
|
191
204
|
end
|
|
192
205
|
return c_result_remove_prefix_path(result,'path',prefix_path)
|
|
193
|
-
when :upload
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
206
|
+
when :upload,:download
|
|
207
|
+
token_type=self.options.get_option(:token_type,:optional)
|
|
208
|
+
# nil if Shares 1.x
|
|
209
|
+
token_type=:aspera if token_type.nil?
|
|
210
|
+
case token_type
|
|
211
|
+
when :aspera,:hybrid
|
|
212
|
+
transfer_paths=case command
|
|
213
|
+
when :upload;[ { :destination => self.transfer.destination_folder('send') } ]
|
|
214
|
+
when :download;self.transfer.ts_source_paths
|
|
215
|
+
end
|
|
216
|
+
# only one request, so only one answer
|
|
217
|
+
transfer_spec=@api_node.create("files/#{command}_setup",{:transfer_requests => [ { transfer_request: {
|
|
218
|
+
paths: transfer_paths
|
|
219
|
+
}.deep_merge(@add_request_param) } ] } )[:data]['transfer_specs'].first['transfer_spec']
|
|
220
|
+
# delete this part, as the returned value contains only destination, and not sources
|
|
221
|
+
transfer_spec.delete('paths') if command.eql?(:upload)
|
|
222
|
+
when :basic
|
|
223
|
+
raise "shall have auth" unless @api_node.params[:auth].is_a?(Hash)
|
|
224
|
+
raise "shall be basic auth" unless @api_node.params[:auth][:type].eql?(:basic)
|
|
225
|
+
transfer_spec={
|
|
226
|
+
'remote_host'=>URI.parse(@api_node.params[:base_url]).host,
|
|
227
|
+
'remote_user'=>Aspera::Node::ACCESS_KEY_TRANSFER_USER,
|
|
228
|
+
'ssh_port'=>Aspera::Node::SSH_PORT_DEFAULT,
|
|
229
|
+
'direction'=>case command;when :upload;'send';when :download;'recv';else raise "Error";end
|
|
230
|
+
}
|
|
231
|
+
else raise "ERROR: token_type #{tt}"
|
|
232
|
+
end
|
|
233
|
+
if [:basic,:hybrid].include?(token_type)
|
|
234
|
+
Aspera::Node.set_ak_basic_token(transfer_spec,@api_node.params[:auth][:username],@api_node.params[:auth][:password])
|
|
235
|
+
end
|
|
209
236
|
return Main.result_transfer(self.transfer.start(transfer_spec,{:src=>:node_gen3}))
|
|
210
237
|
when :api_details
|
|
211
238
|
return { :type=>:single_object, :data => @api_node.params }
|
|
@@ -271,8 +298,8 @@ module Aspera
|
|
|
271
298
|
if self.options.get_option(:once_only,:mandatory)
|
|
272
299
|
skip_ids_persistency=PersistencyActionOnce.new(
|
|
273
300
|
manager: @agents[:persistency],
|
|
274
|
-
data:
|
|
275
|
-
|
|
301
|
+
data: iteration_data,
|
|
302
|
+
id: IdGenerator.from_list(['sync_files',self.options.get_option(:url,:mandatory),self.options.get_option(:username,:mandatory),asyncid]))
|
|
276
303
|
unless iteration_data.first.nil?
|
|
277
304
|
data.select!{|l| l['fnid'].to_i>iteration_data.first}
|
|
278
305
|
end
|
|
@@ -408,9 +435,11 @@ module Aspera
|
|
|
408
435
|
command=self.options.get_next_command([ :list, :modify])
|
|
409
436
|
case command
|
|
410
437
|
when :list
|
|
411
|
-
request_data.deep_merge!({
|
|
412
|
-
resp=@api_node.create('services/rest/transfers/v1/files',request_data)
|
|
413
|
-
|
|
438
|
+
request_data.deep_merge!({'validation'=>validation}) unless validation.nil?
|
|
439
|
+
resp=@api_node.create('services/rest/transfers/v1/files',request_data)[:data]
|
|
440
|
+
resp=JSON.parse(resp) if resp.is_a?(String)
|
|
441
|
+
Log.dump(:resp,resp)
|
|
442
|
+
return {:type=>:object_list,:data=>resp['file_transfer_info_result']['file_transfer_info'],:fields=>["session_uuid","file_id","status","path"]}
|
|
414
443
|
when :modify
|
|
415
444
|
request_data.deep_merge!(validation) unless validation.nil?
|
|
416
445
|
@api_node.update('services/rest/transfers/v1/files',request_data)
|