aspera-cli 4.1.0 → 4.3.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +455 -229
  3. data/docs/Makefile +4 -4
  4. data/docs/README.erb.md +457 -126
  5. data/docs/test_env.conf +19 -2
  6. data/examples/aoc.rb +14 -3
  7. data/examples/faspex4.rb +89 -0
  8. data/lib/aspera/aoc.rb +38 -40
  9. data/lib/aspera/cli/main.rb +65 -33
  10. data/lib/aspera/cli/plugins/aoc.rb +54 -65
  11. data/lib/aspera/cli/plugins/ats.rb +2 -2
  12. data/lib/aspera/cli/plugins/config.rb +158 -137
  13. data/lib/aspera/cli/plugins/faspex.rb +111 -64
  14. data/lib/aspera/cli/plugins/faspex5.rb +35 -48
  15. data/lib/aspera/cli/plugins/node.rb +3 -2
  16. data/lib/aspera/cli/plugins/preview.rb +88 -55
  17. data/lib/aspera/cli/transfer_agent.rb +98 -62
  18. data/lib/aspera/cli/version.rb +1 -1
  19. data/lib/aspera/command_line_builder.rb +48 -31
  20. data/lib/aspera/cos_node.rb +34 -28
  21. data/lib/aspera/environment.rb +2 -2
  22. data/lib/aspera/fasp/aoc.rb +1 -1
  23. data/lib/aspera/fasp/installation.rb +68 -45
  24. data/lib/aspera/fasp/local.rb +89 -45
  25. data/lib/aspera/fasp/manager.rb +3 -0
  26. data/lib/aspera/fasp/node.rb +23 -1
  27. data/lib/aspera/fasp/parameters.rb +57 -86
  28. data/lib/aspera/fasp/parameters.yaml +531 -0
  29. data/lib/aspera/fasp/resume_policy.rb +13 -12
  30. data/lib/aspera/fasp/uri.rb +1 -1
  31. data/lib/aspera/id_generator.rb +22 -0
  32. data/lib/aspera/node.rb +14 -3
  33. data/lib/aspera/oauth.rb +135 -129
  34. data/lib/aspera/persistency_action_once.rb +11 -7
  35. data/lib/aspera/persistency_folder.rb +6 -26
  36. data/lib/aspera/rest.rb +3 -12
  37. data/lib/aspera/secrets.rb +20 -0
  38. data/lib/aspera/sync.rb +40 -35
  39. data/lib/aspera/timer_limiter.rb +22 -0
  40. data/lib/aspera/web_auth.rb +105 -0
  41. metadata +22 -3
  42. data/docs/transfer_spec.html +0 -99
@@ -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,17 @@ module Aspera
17
19
  KEY_NODE='node'
18
20
  KEY_PATH='path'
19
21
  VAL_ALL='ALL'
20
- private_constant :KEY_NODE,:KEY_PATH,:VAL_ALL
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
+ # number is added by CLI
27
+ MAX_ITEMS='max'
28
+ MAX_PAGES='pmax'
29
+ ATOM_PARAMS=['page', 'count', 'startIndex', MAX_ITEMS, MAX_PAGES]
30
+ PUB_LINK_EXTERNAL_MATCH='external_deliveries/'
31
+ private_constant :KEY_NODE,:KEY_PATH,:VAL_ALL,:PACKAGE_MATCH_FIELD,:ATOM_MAILBOXES,:PUB_LINK_EXTERNAL_MATCH
32
+
21
33
  def initialize(env)
22
34
  @api_v3=nil
23
35
  @api_v4=nil
@@ -26,7 +38,8 @@ module Aspera
26
38
  self.options.add_opt_simple(:delivery_info,'package delivery information (extended value)')
27
39
  self.options.add_opt_simple(:source_name,'create package from remote source (by name)')
28
40
  self.options.add_opt_simple(:storage,'Faspex local storage definition')
29
- self.options.add_opt_list(:box,[:inbox,:sent,:archive],'package box')
41
+ self.options.add_opt_simple(:recipient,'use if recipient is a dropbox (with *)')
42
+ self.options.add_opt_list(:box,ATOM_MAILBOXES,'package box')
30
43
  self.options.set_option(:box,:inbox)
31
44
  self.options.parse_options!
32
45
  end
@@ -72,7 +85,7 @@ module Aspera
72
85
  def self.get_source_id(source_list,source_name)
73
86
  source_ids=source_list.select { |i| i['name'].eql?(source_name) }
74
87
  if source_ids.empty?
75
- raise CliError,"No such Faspex source #{field_sym.to_s}: #{field_value} in [#{source_list.map{|i| i[field_sym.to_s]}.join(', ')}]"
88
+ raise CliError,%Q{No such Faspex source "#{source_name}" in [#{source_list.map{|i| %Q{"#{i['name']}"}}.join(', ')}]}
76
89
  end
77
90
  return source_ids.first['id']
78
91
  end
@@ -101,29 +114,57 @@ module Aspera
101
114
  return @api_v4
102
115
  end
103
116
 
104
- ACTIONS=[ :health,:package, :source, :me, :dropbox, :v4, :address_book, :login_methods ]
105
-
106
- # we match recv command on atom feed on this field
107
- PACKAGE_MATCH_FIELD='package_id'
108
-
117
+ # query supports : {"startIndex":10,"count":1,"page":109}
109
118
  def mailbox_all_entries
110
- my_user_name=self.options.get_option(:username,:mandatory)
119
+ recipient_name=self.options.get_option(:recipient,:optional) || self.options.get_option(:username,:mandatory)
120
+ # mailbox is in ATOM_MAILBOXES
111
121
  mailbox=self.options.get_option(:box,:mandatory)
112
- all_inbox_xml=api_v3.call({:operation=>'GET',:subpath=>"#{mailbox}.atom",:headers=>{'Accept'=>'application/xml'}})[:http].body
113
- all_inbox_data=XmlSimple.xml_in(all_inbox_xml, {'ForceArray' => true})
114
- Log.dump(:all_inbox_data,all_inbox_data)
115
- result=all_inbox_data.has_key?('entry') ? all_inbox_data['entry'] : []
116
- result.each do |e|
117
- case mailbox
118
- when :inbox,:archive
119
- recipient=e['to'].select{|i|i['name'].first.eql?(my_user_name)}.first
120
- e[PACKAGE_MATCH_FIELD]=recipient.nil? ? 'n/a' : recipient['recipient_delivery_id'].first
121
- when :sent
122
- e[PACKAGE_MATCH_FIELD]=e['delivery_id'].first
122
+ # parameters
123
+ mailbox_query=self.options.get_option(:query,:optional)
124
+ max_items=nil
125
+ max_pages=nil
126
+ result=[]
127
+ if !mailbox_query.nil?
128
+ raise "query: must be Hash or nil" unless mailbox_query.is_a?(Hash)
129
+ raise "query: supported params: #{ATOM_PARAMS}" unless (mailbox_query.keys-ATOM_PARAMS).empty?
130
+ raise "query: startIndex and page are exclusive" if mailbox_query.has_key?('startIndex') and mailbox_query.has_key?('page')
131
+ max_items=mailbox_query[MAX_ITEMS]
132
+ mailbox_query.delete(MAX_ITEMS)
133
+ max_pages=mailbox_query[MAX_PAGES]
134
+ mailbox_query.delete(MAX_PAGES)
135
+ end
136
+ loop do
137
+ atom_xml=api_v3.call({operation: 'GET',subpath: "#{mailbox}.atom",headers: {'Accept'=>'application/xml'},url_params: mailbox_query})[:http].body
138
+ box_data=XmlSimple.xml_in(atom_xml, {'ForceArray' => true})
139
+ Log.dump(:box_data,box_data)
140
+ items=box_data.has_key?('entry') ? box_data['entry'] : []
141
+ Log.log.debug("new items: #{items.count}")
142
+ # it is the end if page is empty
143
+ break if items.empty?
144
+ items.each do |package|
145
+ package[PACKAGE_MATCH_FIELD]=case mailbox
146
+ when :inbox,:archive
147
+ recipient=package['to'].select{|i|i['name'].first.eql?(recipient_name)}.first
148
+ recipient.nil? ? nil : recipient['recipient_delivery_id'].first
149
+ else # :sent
150
+ package['delivery_id'].first
151
+ end
152
+ # keep only those for the specified recipient
153
+ result.push(package) unless package[PACKAGE_MATCH_FIELD].nil?
123
154
  end
155
+ Log.log.debug("total items: #{result.count}")
156
+ # reach the limit ?
157
+ break if !max_items.nil? and result.count > max_items
158
+ link=box_data['link'].select{|i|i['rel'].eql?('next')}.first
159
+ Log.log.debug("link: #{link}")
160
+ # no next link
161
+ break if link.nil?
162
+ # replace parameters with the ones from next link
163
+ params=CGI.parse(URI.parse(link['href']).query)
164
+ mailbox_query=params.keys.inject({}){|m,i|;m[i]=params[i].first;m}
165
+ Log.log.debug("query: #{mailbox_query}")
166
+ break if !max_pages.nil? and mailbox_query['page'].to_i > max_pages
124
167
  end
125
- # remove dropbox packages
126
- result.select!{|p|p['metadata'].first['field'].select{|j|j['name'].eql?('_dropbox_name')}.empty? rescue false}
127
168
  return result
128
169
  end
129
170
 
@@ -159,6 +200,8 @@ module Aspera
159
200
  return pkgdatares.first
160
201
  end
161
202
 
203
+ ACTIONS=[ :health,:package, :source, :me, :dropbox, :v4, :address_book, :login_methods ]
204
+
162
205
  def execute_action
163
206
  command=self.options.get_next_command(ACTIONS)
164
207
  case command
@@ -208,52 +251,59 @@ module Aspera
208
251
  #Log.dump('transfer_spec',transfer_spec)
209
252
  return Main.result_transfer(self.transfer.start(transfer_spec,{:src=>:node_gen3}))
210
253
  when :recv
211
- public_link_url=self.options.get_option(:link,:optional)
212
- if !public_link_url.nil?
213
- link_data=self.class.get_link_data(public_link_url)
214
- if !link_data[:subpath].match(%r{external_deliveries/})
215
- raise CliBadArgument,"pub link is #{link_data[:subpath]}, expecting external_deliveries/"
254
+ link_url=self.options.get_option(:link,:optional)
255
+ # list of faspex ID/URI to download
256
+ pkg_id_uri=nil
257
+ skip_ids_data=[]
258
+ skip_ids_persistency=nil
259
+ case link_url
260
+ when nil # usual case: no link
261
+ if self.options.get_option(:once_only,:mandatory)
262
+ skip_ids_persistency=PersistencyActionOnce.new(
263
+ manager: @agents[:persistency],
264
+ data: skip_ids_data,
265
+ 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]))
266
+ end
267
+ # get command line parameters
268
+ delivid=self.options.get_option(:id,:mandatory)
269
+ if delivid.eql?(VAL_ALL)
270
+ pkg_id_uri=mailbox_all_entries.map{|i|{:id=>i[PACKAGE_MATCH_FIELD],:uri=>self.class.get_fasp_uri_from_entry(i)}}
271
+ # TODO : remove ids from skip not present in inbox
272
+ # skip_ids_data.select!{|id|pkg_id_uri.select{|p|p[:id].eql?(id)}}
273
+ pkg_id_uri.select!{|i|!skip_ids_data.include?(i[:id])}
274
+ else
275
+ recipient=options.get_option(:recipient,:optional)
276
+ if !recipient.nil? and recipient.start_with?('*')
277
+ raise "Dropbox and Workgroup packages should use link option with faspe:"
278
+ end
279
+ # TODO: delivery id is the right one if package was receive by workgroup
280
+ endpoint=case self.options.get_option(:box,:mandatory)
281
+ when :inbox,:archive;'received'
282
+ when :sent; 'sent'
283
+ end
284
+ entry_xml=api_v3.call({:operation=>'GET',:subpath=>"#{endpoint}/#{delivid}",:headers=>{'Accept'=>'application/xml'}})[:http].body
285
+ package_entry=XmlSimple.xml_in(entry_xml, {'ForceArray' => true})
286
+ pkg_id_uri=[{:id=>delivid,:uri=>self.class.get_fasp_uri_from_entry(package_entry)}]
287
+ end
288
+ when /^faspe:/
289
+ pkg_id_uri=[{:id=>'package',:uri=>link_url}]
290
+ else
291
+ link_data=self.class.get_link_data(link_url)
292
+ if !link_data[:subpath].start_with?(PUB_LINK_EXTERNAL_MATCH)
293
+ raise CliBadArgument,"Pub link is #{link_data[:subpath]}. Expecting #{PUB_LINK_EXTERNAL_MATCH}"
216
294
  end
217
- # Note: unauthenticated API
295
+ # Note: unauthenticated API (autorization is in url params)
218
296
  api_public_link=Rest.new({:base_url=>link_data[:base_url]})
219
297
  pkgdatares=api_public_link.call({:operation=>'GET',:subpath=>link_data[:subpath],:url_params=>{:passcode=>link_data[:query]['passcode']},:headers=>{'Accept'=>'application/xml'}})
220
298
  if !pkgdatares[:http].body.start_with?('<?xml ')
221
- OpenApplication.instance.uri(public_link_url)
299
+ OpenApplication.instance.uri(link_url)
222
300
  raise CliError, 'no such package'
223
301
  end
224
302
  package_entry=XmlSimple.xml_in(pkgdatares[:http].body, {'ForceArray' => false})
303
+ Log.dump(:package_entry,package_entry)
225
304
  transfer_uri=self.class.get_fasp_uri_from_entry(package_entry)
226
- transfer_spec=Fasp::Uri.new(transfer_uri).transfer_spec
227
- transfer_spec['direction']='receive'
228
- return Main.result_transfer(self.transfer.start(transfer_spec,{:src=>:node_gen3}))
305
+ pkg_id_uri=[{:id=>package_entry['id'],:uri=>transfer_uri}]
229
306
  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
307
  Log.dump(:pkg_id_uri,pkg_id_uri)
258
308
  return Main.result_status('no package') if pkg_id_uri.empty?
259
309
  result_transfer=[]
@@ -262,20 +312,17 @@ module Aspera
262
312
  # NOTE: only external users have token in faspe: link !
263
313
  if !transfer_spec.has_key?('token')
264
314
  sanitized=id_uri[:uri].gsub('&','&amp;')
265
- # TODO: file jira
266
- #XXsanitized.gsub!(/%3D%3D$/,'==')
267
- #XXsanitized.gsub!(/%3D$/,'=')
268
315
  xmlpayload='<?xml version="1.0" encoding="UTF-8"?><url-list xmlns="http://schemas.asperasoft.com/xml/url-list"><url href="'+sanitized+'"/></url-list>'
269
316
  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
317
  end
271
318
  transfer_spec['direction']='receive'
272
319
  statuses=self.transfer.start(transfer_spec,{:src=>:node_gen3})
273
- result_transfer.push({'package'=>id_uri[:id],'status'=>statuses.map{|i|i.to_s}.join(',')})
320
+ result_transfer.push({'package'=>id_uri[:id],Main::STATUS_FIELD=>statuses})
274
321
  # skip only if all sessions completed
275
322
  skip_ids_data.push(id_uri[:id]) if TransferAgent.session_status(statuses).eql?(:success)
276
323
  end
277
324
  skip_ids_persistency.save unless skip_ids_persistency.nil?
278
- return {:type=>:object_list,:data=>result_transfer}
325
+ return Main.result_transfer_multiple(result_transfer)
279
326
  end
280
327
  when :source
281
328
  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,64 +41,43 @@ 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
- #raise "JWT to be implemented"
46
+ # currently Faspex 5 beta 3 only supports non-user based apis (e.g. jobs)
47
+ app_client_id=options.get_option(:client_id,:mandatory)
49
48
  @api_v5=Rest.new({
50
- :base_url => faxpex5_api_base_url,
49
+ :base_url => faxpex5_api_v5_url,
51
50
  :auth => {
52
51
  :type => :oauth2,
53
52
  :base_url => faxpex5_api_auth_url,
54
53
  :grant => :jwt,
55
- :client_id => options.get_option(:client_id,:mandatory),
54
+ :f5_username => options.get_option(:username,:mandatory),
55
+ :f5_password => options.get_option(:password,:mandatory),
56
+ :client_id => app_client_id,
56
57
  :client_secret => options.get_option(:client_secret,:mandatory),
57
- #:redirect_uri => options.get_option(:redirect_uri,:mandatory),
58
- :jwt_subject => "client:#{options.get_option(:client_id,:mandatory)}", # TODO Mmmm
58
+ :jwt_subject => "client:#{app_client_id}", # TODO Mmmm
59
+ :jwt_audience => app_client_id, # TODO Mmmm
59
60
  :jwt_private_key_obj => OpenSSL::PKey::RSA.new(options.get_option(:private_key,:mandatory)),
60
- :jwt_audience =>options.get_option(:client_id,:mandatory), # TODO Mmmm
61
- #:token_field =>'auth_token',
62
- #:path_token => 'authenticate',
63
- #:path_authorize => :unused,
64
- #:userpass_body => {name: options.get_option(:username,:mandatory),password: options.get_option(:password,:mandatory)}
61
+ :jwt_headers => {typ: 'JWT'}
65
62
  }})
66
- # former version
67
- # # get parameters
68
- # faxpex5_username=options.get_option(:username,:mandatory)
69
- # faxpex5_password=options.get_option(:password,:mandatory)
70
- # # create object for REST calls to Shares2
71
- # @api_v5=Rest.new({
72
- # :base_url => faxpex5_api_base_url,
73
- # :auth => {
74
- # :type => :oauth2,
75
- # :base_url => faxpex5_api_base_url,
76
- # :grant => :body_data,
77
- # :token_field =>'auth_token',
78
- # :path_token => 'authenticate',
79
- # :path_authorize => :unused,
80
- # :userpass_body => {name: faxpex5_username,password: faxpex5_password}
81
- # }})
82
63
  end
83
64
  end
84
65
 
66
+ ACTIONS=[ :node, :package, :auth_client, :jobs ]
67
+
85
68
  #
86
69
  def execute_action
87
70
  set_api
88
71
  command=options.get_next_command(ACTIONS)
89
72
  case command
90
73
  when :auth_client
91
- api_auth=Rest.new(@api_v5.params.merge({base_url: @api_v5.params[:base_url].gsub(/api\/v5$/,'auth')}))
74
+ api_auth=Rest.new(@api_v5.params.merge({base_url: "#{@faxpex5_api_base_url}/auth"}))
92
75
  return self.entity_action(api_auth,'oauth_clients',nil,:id,nil,true)
93
76
  when :node
94
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)
95
81
  when :package
96
82
  command=options.get_next_command([:list,:show,:send,:receive])
97
83
  case command
@@ -103,7 +89,7 @@ module Aspera
103
89
  return {:type => :single_object, :data=>@api_v5.read("packages/#{id}")[:data]}
104
90
  when :send
105
91
  parameters=options.get_option(:value,:mandatory)
106
- raise CliBadArgument,'package value must be hash, refer to API' unless parameters.is_a?(Hash)
92
+ raise CliBadArgument,'value must be hash, refer to API' unless parameters.is_a?(Hash)
107
93
  package=@api_v5.create('packages',parameters)[:data]
108
94
  transfer_spec=@api_v5.create("packages/#{package['id']}/transfer_spec/upload",{transfer_type: 'Connect'})[:data]
109
95
  transfer_spec.delete('authentication')
@@ -115,16 +101,17 @@ module Aspera
115
101
  skip_ids_data=[]
116
102
  skip_ids_persistency=nil
117
103
  if options.get_option(:once_only,:mandatory)
104
+ # read ids from persistency
118
105
  skip_ids_persistency=PersistencyActionOnce.new(
119
106
  manager: @agents[:persistency],
120
- data: skip_ids_data,
121
- ids: ['faspex_recv',options.get_option(:url,:mandatory),options.get_option(:username,:mandatory),pkg_type])
107
+ data: skip_ids_data,
108
+ id: IdGenerator.from_list(['faspex_recv',options.get_option(:url,:mandatory),options.get_option(:username,:mandatory),pkg_type]))
122
109
  end
123
110
  if pack_id.eql?(VAL_ALL)
124
- # todo: if packages have same name, they will overwrite
111
+ # TODO: if packages have same name, they will overwrite
125
112
  parameters=options.get_option(:value,:optional)
126
- parameters||={"type"=>"received","subtype"=>"mypackages","limit"=>1000}
127
- raise CliBadArgument,'value filter must be hash (API GET)' unless parameters.is_a?(Hash)
113
+ parameters||={'type'=>'received','subtype'=>'mypackages','limit'=>1000}
114
+ raise CliBadArgument,'value filter must be Hash (API GET)' unless parameters.is_a?(Hash)
128
115
  package_ids=@api_v5.read('packages',parameters)[:data]['packages'].map{|p|p['id']}
129
116
  package_ids.select!{|i|!skip_ids_data.include?(i)}
130
117
  end
@@ -134,12 +121,12 @@ module Aspera
134
121
  transfer_spec=@api_v5.create("packages/#{id}/transfer_spec/download",{transfer_type: 'Connect', type: pkg_type})[:data]
135
122
  transfer_spec.delete('authentication')
136
123
  statuses=self.transfer.start(transfer_spec,{:src=>:node_gen3})
137
- result_transfer.push({'package'=>id,'status'=>statuses.map{|i|i.to_s}.join(',')})
124
+ result_transfer.push({'package'=>id,Main::STATUS_FIELD=>statuses})
138
125
  # skip only if all sessions completed
139
126
  skip_ids_data.push(id) if TransferAgent.session_status(statuses).eql?(:success)
140
127
  end
141
128
  skip_ids_persistency.save unless skip_ids_persistency.nil?
142
- return {:type=>:object_list,:data=>result_transfer}
129
+ return Main.result_transfer_multiple(result_transfer)
143
130
  end
144
131
  end
145
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
 
@@ -271,8 +272,8 @@ module Aspera
271
272
  if self.options.get_option(:once_only,:mandatory)
272
273
  skip_ids_persistency=PersistencyActionOnce.new(
273
274
  manager: @agents[:persistency],
274
- data: iteration_data,
275
- ids: ['sync_files',self.options.get_option(:url,:mandatory),self.options.get_option(:username,:mandatory),asyncid])
275
+ data: iteration_data,
276
+ id: IdGenerator.from_list(['sync_files',self.options.get_option(:url,:mandatory),self.options.get_option(:username,:mandatory),asyncid]))
276
277
  unless iteration_data.first.nil?
277
278
  data.select!{|l| l['fnid'].to_i>iteration_data.first}
278
279
  end