aspera-cli 4.7.0 → 4.8.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 (94) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +1 -0
  3. data/README.md +844 -861
  4. data/bin/ascli +20 -1
  5. data/bin/asession +37 -34
  6. data/docs/test_env.conf +11 -3
  7. data/examples/aoc.rb +13 -12
  8. data/examples/dascli +26 -0
  9. data/examples/faspex4.rb +34 -29
  10. data/examples/transfer.rb +30 -29
  11. data/lib/aspera/aoc.rb +151 -143
  12. data/lib/aspera/ascmd.rb +56 -45
  13. data/lib/aspera/ats_api.rb +6 -5
  14. data/lib/aspera/cli/basic_auth_plugin.rb +18 -16
  15. data/lib/aspera/cli/extended_value.rb +32 -30
  16. data/lib/aspera/cli/formater.rb +103 -111
  17. data/lib/aspera/cli/info.rb +2 -1
  18. data/lib/aspera/cli/listener/line_dump.rb +1 -0
  19. data/lib/aspera/cli/listener/logger.rb +1 -0
  20. data/lib/aspera/cli/listener/progress.rb +13 -12
  21. data/lib/aspera/cli/listener/progress_multi.rb +21 -20
  22. data/lib/aspera/cli/main.rb +106 -89
  23. data/lib/aspera/cli/manager.rb +96 -85
  24. data/lib/aspera/cli/plugin.rb +50 -32
  25. data/lib/aspera/cli/plugins/alee.rb +6 -5
  26. data/lib/aspera/cli/plugins/aoc.rb +521 -426
  27. data/lib/aspera/cli/plugins/ats.rb +84 -83
  28. data/lib/aspera/cli/plugins/bss.rb +30 -27
  29. data/lib/aspera/cli/plugins/config.rb +483 -397
  30. data/lib/aspera/cli/plugins/console.rb +17 -15
  31. data/lib/aspera/cli/plugins/cos.rb +26 -35
  32. data/lib/aspera/cli/plugins/faspex.rb +201 -168
  33. data/lib/aspera/cli/plugins/faspex5.rb +109 -74
  34. data/lib/aspera/cli/plugins/node.rb +378 -189
  35. data/lib/aspera/cli/plugins/orchestrator.rb +71 -65
  36. data/lib/aspera/cli/plugins/preview.rb +131 -122
  37. data/lib/aspera/cli/plugins/server.rb +94 -93
  38. data/lib/aspera/cli/plugins/shares.rb +42 -28
  39. data/lib/aspera/cli/plugins/sync.rb +15 -14
  40. data/lib/aspera/cli/transfer_agent.rb +56 -52
  41. data/lib/aspera/cli/version.rb +2 -1
  42. data/lib/aspera/colors.rb +29 -28
  43. data/lib/aspera/command_line_builder.rb +50 -43
  44. data/lib/aspera/cos_node.rb +64 -38
  45. data/lib/aspera/data_repository.rb +1 -0
  46. data/lib/aspera/environment.rb +18 -8
  47. data/lib/aspera/fasp/agent_base.rb +26 -23
  48. data/lib/aspera/fasp/agent_connect.rb +35 -30
  49. data/lib/aspera/fasp/agent_direct.rb +68 -60
  50. data/lib/aspera/fasp/agent_httpgw.rb +71 -64
  51. data/lib/aspera/fasp/agent_node.rb +24 -23
  52. data/lib/aspera/fasp/agent_trsdk.rb +19 -20
  53. data/lib/aspera/fasp/error.rb +2 -1
  54. data/lib/aspera/fasp/error_info.rb +79 -68
  55. data/lib/aspera/fasp/installation.rb +122 -114
  56. data/lib/aspera/fasp/listener.rb +1 -0
  57. data/lib/aspera/fasp/parameters.rb +44 -41
  58. data/lib/aspera/fasp/resume_policy.rb +14 -11
  59. data/lib/aspera/fasp/transfer_spec.rb +6 -5
  60. data/lib/aspera/fasp/uri.rb +25 -24
  61. data/lib/aspera/faspex_gw.rb +83 -72
  62. data/lib/aspera/hash_ext.rb +10 -12
  63. data/lib/aspera/id_generator.rb +8 -7
  64. data/lib/aspera/keychain/encrypted_hash.rb +60 -45
  65. data/lib/aspera/keychain/macos_security.rb +26 -24
  66. data/lib/aspera/log.rb +34 -38
  67. data/lib/aspera/nagios.rb +14 -13
  68. data/lib/aspera/node.rb +19 -19
  69. data/lib/aspera/oauth.rb +121 -101
  70. data/lib/aspera/open_application.rb +6 -5
  71. data/lib/aspera/persistency_action_once.rb +9 -8
  72. data/lib/aspera/persistency_folder.rb +10 -9
  73. data/lib/aspera/preview/file_types.rb +261 -266
  74. data/lib/aspera/preview/generator.rb +74 -73
  75. data/lib/aspera/preview/image_error.png +0 -0
  76. data/lib/aspera/preview/options.rb +7 -6
  77. data/lib/aspera/preview/utils.rb +30 -33
  78. data/lib/aspera/preview/video_error.png +0 -0
  79. data/lib/aspera/proxy_auto_config.rb +25 -23
  80. data/lib/aspera/rest.rb +73 -74
  81. data/lib/aspera/rest_call_error.rb +1 -0
  82. data/lib/aspera/rest_error_analyzer.rb +11 -9
  83. data/lib/aspera/rest_errors_aspera.rb +5 -4
  84. data/lib/aspera/secret_hider.rb +68 -0
  85. data/lib/aspera/ssh.rb +12 -10
  86. data/lib/aspera/sync.rb +49 -47
  87. data/lib/aspera/temp_file_manager.rb +7 -5
  88. data/lib/aspera/timer_limiter.rb +9 -8
  89. data/lib/aspera/uri_reader.rb +11 -14
  90. data/lib/aspera/web_auth.rb +17 -15
  91. data.tar.gz.sig +0 -0
  92. metadata +117 -34
  93. metadata.gz.sig +2 -0
  94. data/bin/dascli +0 -13
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'aspera/cli/basic_auth_plugin'
3
4
  require 'aspera/nagios'
4
5
  require 'aspera/hash_ext'
@@ -14,49 +15,54 @@ module Aspera
14
15
  class Node < BasicAuthPlugin
15
16
  class << self
16
17
  def detect(base_url)
17
- api=Rest.new({ base_url: base_url})
18
- result=api.call({ operation: 'GET', subpath: 'ping'})
18
+ api = Rest.new({ base_url: base_url})
19
+ result = api.call({ operation: 'GET', subpath: 'ping'})
19
20
  if result[:http].body.eql?('')
20
21
  return { product: :node, version: 'unknown'}
21
22
  end
22
23
  return nil
23
24
  end
24
25
  end
25
- SAMPLE_SOAP_CALL='<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="urn:Aspera:XML:FASPSessionNET:2009/11:Types"><soapenv:Header></soapenv:Header><soapenv:Body><typ:GetSessionInfoRequest><SessionFilter><SessionStatus>running</SessionStatus></SessionFilter></typ:GetSessionInfoRequest></soapenv:Body></soapenv:Envelope>'
26
- private_constant :SAMPLE_SOAP_CALL
26
+ SAMPLE_SOAP_CALL = '<?xml version="1.0" encoding="UTF-8"?>'\
27
+ '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="urn:Aspera:XML:FASPSessionNET:2009/11:Types">'\
28
+ '<soapenv:Header></soapenv:Header>'\
29
+ '<soapenv:Body><typ:GetSessionInfoRequest><SessionFilter><SessionStatus>running</SessionStatus></SessionFilter></typ:GetSessionInfoRequest></soapenv:Body>'\
30
+ '</soapenv:Envelope>'
31
+ SEARCH_REMOVE_FIELDS=%w[basename permissions].freeze
32
+ private_constant :SAMPLE_SOAP_CALL,:SEARCH_REMOVE_FIELDS
27
33
 
28
34
  def initialize(env)
29
35
  super(env)
30
- # this is added to some requests , for instance to add tags (COS)
36
+ # this is added to transfer spec, for instance to add tags (COS)
31
37
  @add_request_param = env[:add_request_param] || {}
32
38
  options.add_opt_simple(:validator,'identifier of validator (optional for central)')
33
39
  options.add_opt_simple(:asperabrowserurl,'URL for simple aspera web ui')
34
40
  options.add_opt_simple(:sync_name,'sync name')
35
- options.add_opt_list(:token_type,[:aspera,:basic,:hybrid],'Type of token used for transfers')
41
+ options.add_opt_list(:token_type,%i[aspera basic hybrid],'Type of token used for transfers')
36
42
  options.set_option(:asperabrowserurl,'https://asperabrowser.mybluemix.net')
37
43
  options.set_option(:token_type,:aspera)
38
44
  options.parse_options!
39
45
  return if env[:man_only]
40
- @api_node=
41
- if env.has_key?(:node_api)
42
- env[:node_api]
43
- elsif options.get_option(:password,:mandatory).start_with?('Bearer ')
44
- # info is provided like node_info of aoc
45
- Rest.new({
46
- base_url: options.get_option(:url,:mandatory),
47
- headers: {
48
- 'Authorization' => options.get_option(:password,:mandatory),
49
- 'X-Aspera-AccessKey' => options.get_option(:username,:mandatory)
50
- }
51
- })
52
- else
53
- # this is normal case
54
- basic_auth_api
55
- end
46
+ @api_node =
47
+ if env.has_key?(:node_api)
48
+ env[:node_api]
49
+ elsif options.get_option(:password,is_type: :mandatory).start_with?('Bearer ')
50
+ # info is provided like node_info of aoc
51
+ Rest.new({
52
+ base_url: options.get_option(:url,is_type: :mandatory),
53
+ headers: {
54
+ 'X-Aspera-AccessKey' => options.get_option(:username,is_type: :mandatory),
55
+ 'Authorization' => options.get_option(:password,is_type: :mandatory)
56
+ }
57
+ })
58
+ else
59
+ # this is normal case
60
+ basic_auth_api
61
+ end
56
62
  end
57
63
 
58
64
  def c_textify_browse(table_data)
59
- return table_data.map {|i| i['permissions']=i['permissions'].map { |x| x['name'] }.join(','); i }
65
+ return table_data.map {|i| i['permissions'] = i['permissions'].map { |x| x['name'] }.join(','); i }
60
66
  end
61
67
 
62
68
  # key/value is defined in main in hash_table
@@ -64,7 +70,7 @@ module Aspera
64
70
  list.each_index do |i|
65
71
  next unless name_list.include?(list[i]['key'])
66
72
  list[i]['value'].each do |item|
67
- list.push({'key'=>item['name'],'value'=>item['value']})
73
+ list.push({'key' => item['name'],'value' => item['value']})
68
74
  end
69
75
  list.delete_at(i)
70
76
  # continue at same index because we delete current one
@@ -78,11 +84,11 @@ module Aspera
78
84
  case result[:type]
79
85
  when :object_list
80
86
  result[:data].each do |item|
81
- item[column]=item[column][path_prefix.length..-1] if item[column].start_with?(path_prefix)
87
+ item[column] = item[column][path_prefix.length..-1] if item[column].start_with?(path_prefix)
82
88
  end
83
89
  when :single_object
84
- item=result[:data]
85
- item[column]=item[column][path_prefix.length..-1] if item[column].start_with?(path_prefix)
90
+ item = result[:data]
91
+ item[column] = item[column][path_prefix.length..-1] if item[column].start_with?(path_prefix)
86
92
  end
87
93
  end
88
94
  return result
@@ -90,39 +96,39 @@ module Aspera
90
96
 
91
97
  # translates paths results into CLI result, and removes prefix
92
98
  def c_result_translate_rem_prefix(resp,type,success_msg,path_prefix)
93
- resres={ data: [], type: :object_list, fields: [type,'result']}
99
+ resres = { data: [], type: :object_list, fields: [type,'result']}
94
100
  JSON.parse(resp[:http].body)['paths'].each do |p|
95
- result=success_msg
101
+ result = success_msg
96
102
  if p.has_key?('error')
97
103
  Log.log.error("#{p['error']['user_message']} : #{p['path']}")
98
- result='ERROR: '+p['error']['user_message']
104
+ result = 'ERROR: ' + p['error']['user_message']
99
105
  end
100
- resres[:data].push({type=>p['path'],'result'=>result})
106
+ resres[:data].push({type => p['path'],'result' => result})
101
107
  end
102
108
  return c_result_remove_prefix_path(resres,type,path_prefix)
103
109
  end
104
110
 
105
111
  # get path arguments from command line, and add prefix
106
112
  def get_next_arg_add_prefix(path_prefix,name,number=:single)
107
- thepath=options.get_next_argument(name,number)
113
+ thepath = options.get_next_argument(name,expected: number)
108
114
  return thepath if path_prefix.nil?
109
115
  return File.join(path_prefix,thepath) if thepath.is_a?(String)
110
116
  return thepath.map {|p| File.join(path_prefix,p)} if thepath.is_a?(Array)
111
117
  raise StandardError,'expect: nil, String or Array'
112
118
  end
113
119
 
114
- SIMPLE_ACTIONS=[:health,:events, :space, :info, :license, :mkdir, :mklink, :mkfile, :rename, :delete, :search]
120
+ SIMPLE_ACTIONS = %i[health events space info license mkdir mklink mkfile rename delete search].freeze
115
121
 
116
- COMMON_ACTIONS=[:browse, :upload, :download, :api_details].concat(SIMPLE_ACTIONS)
122
+ COMMON_ACTIONS = %i[browse upload download api_details].concat(SIMPLE_ACTIONS).freeze
117
123
 
118
124
  # common API to node and Shares
119
125
  # prefix_path is used to list remote sources in Faspex
120
126
  def execute_simple_common(command,prefix_path)
121
127
  case command
122
128
  when :health
123
- nagios=Nagios.new
129
+ nagios = Nagios.new
124
130
  begin
125
- info=@api_node.read('info')[:data]
131
+ info = @api_node.read('info')[:data]
126
132
  nagios.add_ok('node api','accessible')
127
133
  nagios.check_time_offset(info['current_time'],'node api')
128
134
  nagios.check_product_version('node api','entsrv', info['version'])
@@ -130,126 +136,130 @@ module Aspera
130
136
  nagios.add_critical('node api',e.to_s)
131
137
  end
132
138
  begin
133
- @api_node.call({ operation: 'POST', subpath: 'services/soap/Transfer-201210',
134
- headers: {'Content-Type'=>'text/xml;charset=UTF-8','SOAPAction'=>'FASPSessionNET-200911#GetSessionInfo'}, text_body_params: SAMPLE_SOAP_CALL})[:http].body
139
+ @api_node.call(
140
+ operation: 'POST',
141
+ subpath: 'services/soap/Transfer-201210',
142
+ headers: {'Content-Type' => 'text/xml;charset=UTF-8','SOAPAction' => 'FASPSessionNET-200911#GetSessionInfo'},
143
+ text_body_params: SAMPLE_SOAP_CALL)[:http].body
135
144
  nagios.add_ok('central','accessible by node')
136
145
  rescue StandardError => e
137
146
  nagios.add_critical('central',e.to_s)
138
147
  end
139
148
  return nagios.result
140
149
  when :events
141
- events=@api_node.read('events',options.get_option(:value,:optional))[:data]
150
+ events = @api_node.read('events',options.get_option(:value))[:data]
142
151
  return { type: :object_list, data: events}
143
152
  when :info
144
- node_info=@api_node.read('info')[:data]
145
- return { type: :single_object, data: node_info, textify: lambda { |table_data| c_textify_bool_list_result(table_data,['capabilities','settings'])}}
153
+ node_info = @api_node.read('info')[:data]
154
+ return { type: :single_object, data: node_info, textify: lambda { |table_data| c_textify_bool_list_result(table_data,%w[capabilities settings])}}
146
155
  when :license # requires: asnodeadmin -mu <node user> --acl-add=internal --internal
147
- node_license=@api_node.read('license')[:data]
156
+ node_license = @api_node.read('license')[:data]
148
157
  if node_license['failure'].is_a?(String) && node_license['failure'].include?('ACL')
149
158
  Log.log.error('server must have: asnodeadmin -mu <node user> --acl-add=internal --internal')
150
159
  end
151
160
  return { type: :single_object, data: node_license}
152
161
  when :delete
153
162
  paths_to_delete = get_next_arg_add_prefix(prefix_path,'file list',:multiple)
154
- resp=@api_node.create('files/delete',{ paths: paths_to_delete.map{|i| {'path'=>i.start_with?('/') ? i : '/'+i} }})
163
+ resp = @api_node.create('files/delete',{ paths: paths_to_delete.map{|i| {'path' => i.start_with?('/') ? i : '/' + i} }})
155
164
  return c_result_translate_rem_prefix(resp,'file','deleted',prefix_path)
156
165
  when :search
157
166
  search_root = get_next_arg_add_prefix(prefix_path,'search root')
158
- parameters={'path'=>search_root}
159
- other_options=options.get_option(:value,:optional)
167
+ parameters = {'path' => search_root}
168
+ other_options = options.get_option(:value)
160
169
  parameters.merge!(other_options) unless other_options.nil?
161
- resp=@api_node.create('files/search',parameters)
162
- result={ type: :object_list, data: resp[:data]['items']}
170
+ resp = @api_node.create('files/search',parameters)
171
+ result = { type: :object_list, data: resp[:data]['items']}
163
172
  return Main.result_empty if result[:data].empty?
164
- result[:fields]=result[:data].first.keys.reject{|i|['basename','permissions'].include?(i)}
173
+ result[:fields] = result[:data].first.keys.reject{|i|SEARCH_REMOVE_FIELDS.include?(i)}
165
174
  self.format.display_status("Items: #{resp[:data]['item_count']}/#{resp[:data]['total_count']}")
166
175
  self.format.display_status("params: #{resp[:data]['parameters'].keys.map{|k|"#{k}:#{resp[:data]['parameters'][k]}"}.join(',')}")
167
176
  return c_result_remove_prefix_path(result,'path',prefix_path)
168
177
  when :space
169
178
  # TODO: could be a list of path
170
- path_list=get_next_arg_add_prefix(prefix_path,'folder path or ext.val. list')
171
- path_list=[path_list] unless path_list.is_a?(Array)
172
- resp=@api_node.create('space',{ 'paths' => path_list.map {|i| { path: i} } })
173
- result={ data: resp[:data]['paths'], type: :object_list}
179
+ path_list = get_next_arg_add_prefix(prefix_path,'folder path or ext.val. list')
180
+ path_list = [path_list] unless path_list.is_a?(Array)
181
+ resp = @api_node.create('space',{ 'paths' => path_list.map {|i| { path: i} } })
182
+ result = { data: resp[:data]['paths'], type: :object_list}
174
183
  #return c_result_translate_rem_prefix(resp,'folder','created',prefix_path)
175
184
  return c_result_remove_prefix_path(result,'path',prefix_path)
176
185
  when :mkdir
177
- path_list=get_next_arg_add_prefix(prefix_path,'folder path or ext.val. list')
178
- path_list=[path_list] unless path_list.is_a?(Array)
186
+ path_list = get_next_arg_add_prefix(prefix_path,'folder path or ext.val. list')
187
+ path_list = [path_list] unless path_list.is_a?(Array)
179
188
  #TODO: a command for that ?
180
189
  #resp=@api_node.create('space',{ "paths" => path_list.map {|i| { type: :directory, path: i} } } )
181
- resp=@api_node.create('files/create',{ 'paths' => [{ type: :directory, path: path_list }] })
190
+ resp = @api_node.create('files/create',{ 'paths' => [{ type: :directory, path: path_list }] })
182
191
  return c_result_translate_rem_prefix(resp,'folder','created',prefix_path)
183
192
  when :mklink
184
- target=get_next_arg_add_prefix(prefix_path,'target')
185
- path_list=get_next_arg_add_prefix(prefix_path,'link path')
186
- resp=@api_node.create('files/create',{ 'paths' => [{ type: :symbolic_link, path: path_list, target: { path: target} }] })
193
+ target = get_next_arg_add_prefix(prefix_path,'target')
194
+ path_list = get_next_arg_add_prefix(prefix_path,'link path')
195
+ resp = @api_node.create('files/create',{ 'paths' => [{ type: :symbolic_link, path: path_list, target: { path: target} }] })
187
196
  return c_result_translate_rem_prefix(resp,'folder','created',prefix_path)
188
197
  when :mkfile
189
- path_list=get_next_arg_add_prefix(prefix_path,'file path')
190
- contents64=Base64.strict_encode64(options.get_next_argument('contents'))
191
- resp=@api_node.create('files/create',{ 'paths' => [{ type: :file, path: path_list, contents: contents64 }] })
198
+ path_list = get_next_arg_add_prefix(prefix_path,'file path')
199
+ contents64 = Base64.strict_encode64(options.get_next_argument('contents'))
200
+ resp = @api_node.create('files/create',{ 'paths' => [{ type: :file, path: path_list, contents: contents64 }] })
192
201
  return c_result_translate_rem_prefix(resp,'folder','created',prefix_path)
193
202
  when :rename
194
- path_base=get_next_arg_add_prefix(prefix_path,'path_base')
195
- path_src=get_next_arg_add_prefix(prefix_path,'path_src')
196
- path_dst=get_next_arg_add_prefix(prefix_path,'path_dst')
197
- resp=@api_node.create('files/rename',{ 'paths' => [{ 'path' => path_base, 'source' => path_src, 'destination' => path_dst }] })
203
+ path_base = get_next_arg_add_prefix(prefix_path,'path_base')
204
+ path_src = get_next_arg_add_prefix(prefix_path,'path_src')
205
+ path_dst = get_next_arg_add_prefix(prefix_path,'path_dst')
206
+ resp = @api_node.create('files/rename',{ 'paths' => [{ 'path' => path_base, 'source' => path_src, 'destination' => path_dst }] })
198
207
  return c_result_translate_rem_prefix(resp,'entry','moved',prefix_path)
199
208
  when :browse
200
- thepath=get_next_arg_add_prefix(prefix_path,'path')
201
- query={ path: thepath}
202
- additional_query=options.get_option(:query,:optional)
209
+ thepath = get_next_arg_add_prefix(prefix_path,'path')
210
+ query = { path: thepath}
211
+ additional_query = options.get_option(:query)
203
212
  query.merge!(additional_query) unless additional_query.nil?
204
- send_result=@api_node.create('files/browse', query)[:data]
213
+ send_result = @api_node.create('files/browse', query)[:data]
205
214
  #example: send_result={'items'=>[{'file'=>"filename1","permissions"=>[{'name'=>'read'},{'name'=>'write'}]}]}
206
215
  # if there is no items
207
216
  case send_result['self']['type']
208
217
  when 'directory','container' # directory: node, container: shares
209
- result={ data: send_result['items'], type: :object_list, textify: lambda { |table_data| c_textify_browse(table_data) } }
218
+ result = { data: send_result['items'], type: :object_list, textify: lambda { |table_data| c_textify_browse(table_data) } }
210
219
  self.format.display_status("Items: #{send_result['item_count']}/#{send_result['total_count']}")
211
220
  else # 'file','symbolic_link'
212
- result={ data: send_result['self'], type: :single_object}
221
+ result = { data: send_result['self'], type: :single_object}
213
222
  #result={ data: [send_result['self']] , type: :object_list, textify: lambda { |table_data| c_textify_browse(table_data) } }
214
223
  #raise "unknown type: #{send_result['self']['type']}"
215
224
  end
216
225
  return c_result_remove_prefix_path(result,'path',prefix_path)
217
226
  when :upload,:download
218
- token_type=options.get_option(:token_type,:optional)
227
+ token_type = options.get_option(:token_type)
219
228
  # nil if Shares 1.x
220
- token_type=:aspera if token_type.nil?
229
+ token_type = :aspera if token_type.nil?
221
230
  case token_type
222
231
  when :aspera,:hybrid
223
- transfer_paths=
224
- case command
225
- when :upload then[{ destination: transfer.destination_folder('send') }]
226
- when :download then transfer.ts_source_paths
227
- end
232
+ # empty transfer spec for authorization request
233
+ request_transfer_spec={}
234
+ # set requested paths depending on direction
235
+ request_transfer_spec[:paths] = command.eql?(:download) ? transfer.ts_source_paths : [{ destination: transfer.destination_folder('send') }]
236
+ # add fixed parameters if any (for COS)
237
+ request_transfer_spec.deep_merge!(@add_request_param)
238
+ # prepare payload for single request
239
+ setup_payload={transfer_requests: [{transfer_request: request_transfer_spec}]}
228
240
  # only one request, so only one answer
229
- transfer_spec=@api_node.create("files/#{command}_setup",{ transfer_requests: [{ transfer_request: {
230
- paths: transfer_paths
231
- }.deep_merge(@add_request_param) }] })[:data]['transfer_specs'].first['transfer_spec']
241
+ transfer_spec = @api_node.create("files/#{command}_setup",setup_payload)[:data]['transfer_specs'].first['transfer_spec']
232
242
  # delete this part, as the returned value contains only destination, and not sources
233
243
  transfer_spec.delete('paths') if command.eql?(:upload)
234
244
  when :basic
235
245
  raise 'shall have auth' unless @api_node.params[:auth].is_a?(Hash)
236
246
  raise 'shall be basic auth' unless @api_node.params[:auth][:type].eql?(:basic)
237
- ts_direction=
238
- case command
239
- when :upload then Fasp::TransferSpec::DIRECTION_SEND
240
- when :download then Fasp::TransferSpec::DIRECTION_RECEIVE
241
- else raise 'Error: need upload or download'
242
- end
243
- transfer_spec={
244
- 'remote_host' =>URI.parse(@api_node.params[:base_url]).host,
245
- 'remote_user' =>Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER,
246
- 'ssh_port' =>Aspera::Fasp::TransferSpec::SSH_PORT,
247
- 'direction' =>ts_direction,
248
- 'destination_root'=>transfer.destination_folder(ts_direction)
247
+ ts_direction =
248
+ case command
249
+ when :upload then Fasp::TransferSpec::DIRECTION_SEND
250
+ when :download then Fasp::TransferSpec::DIRECTION_RECEIVE
251
+ else raise 'Error: need upload or download'
252
+ end
253
+ transfer_spec = {
254
+ 'remote_host' => URI.parse(@api_node.params[:base_url]).host,
255
+ 'remote_user' => Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER,
256
+ 'ssh_port' => Aspera::Fasp::TransferSpec::SSH_PORT,
257
+ 'direction' => ts_direction,
258
+ 'destination_root' => transfer.destination_folder(ts_direction)
249
259
  }.deep_merge(@add_request_param)
250
260
  else raise "ERROR: token_type #{tt}"
251
261
  end
252
- if [:basic,:hybrid].include?(token_type)
262
+ if %i[basic hybrid].include?(token_type)
253
263
  Aspera::Node.set_ak_basic_token(transfer_spec,@api_node.params[:auth][:username],@api_node.params[:auth][:password])
254
264
  end
255
265
  return Main.result_transfer(transfer.start(transfer_spec,{ src: :node_gen3}))
@@ -258,173 +268,352 @@ headers: {'Content-Type'=>'text/xml;charset=UTF-8','SOAPAction'=>'FASPSessionNET
258
268
  end
259
269
  end
260
270
 
271
+ # navigate the path from given file id
272
+ # @param id initial file id
273
+ # @param path file path
274
+ # @return {.api,.file_id}
275
+ def resolve_api_fid(id, path)
276
+ # TODO: implement
277
+ return {api: @api_node, file_id: id}
278
+ end
279
+
280
+ NODE4_COMMANDS = %i[browse find mkdir rename delete upload download http_node_download file permission bearer_token_node node_info].freeze
281
+
282
+ def execute_node_gen4_command(command_repo, top_file_id)
283
+ #@api_node
284
+ case command_repo
285
+ when :node_info
286
+ thepath = options.get_next_argument('path')
287
+ apifid = resolve_api_fid(top_file_id,thepath)
288
+ apifid[:api] = aoc_api.get_node_api(apifid[:node_info], use_secret: false)
289
+ return {type: :single_object,data: {
290
+ url: apifid[:node_info]['url'],
291
+ username: apifid[:node_info]['access_key'],
292
+ password: apifid[:api].oauth_token,
293
+ root_id: apifid[:file_id]
294
+ }}
295
+ when :browse
296
+ thepath = options.get_next_argument('path')
297
+ apifid = resolve_api_fid(top_file_id,thepath)
298
+ file_info = apifid[:api].read("files/#{apifid[:file_id]}")[:data]
299
+ if file_info['type'].eql?('folder')
300
+ result = apifid[:api].read("files/#{apifid[:file_id]}/files",options.get_option(:value))
301
+ items = result[:data]
302
+ self.format.display_status("Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}")
303
+ else
304
+ items = [file_info]
305
+ end
306
+ return {type: :object_list,data: items,fields: %w[name type recursive_size size modified_time access_level]}
307
+ when :find
308
+ thepath = options.get_next_argument('path')
309
+ apifid = resolve_api_fid(top_file_id,thepath)
310
+ test_block = Aspera::Node.file_matcher(options.get_option(:value))
311
+ return {type: :object_list,data: aoc_api.find_files(apifid,test_block),fields: ['path']}
312
+ when :mkdir
313
+ thepath = options.get_next_argument('path')
314
+ containing_folder_path = thepath.split(AoC::PATH_SEPARATOR)
315
+ new_folder = containing_folder_path.pop
316
+ apifid = resolve_api_fid(top_file_id,containing_folder_path.join(AoC::PATH_SEPARATOR))
317
+ result = apifid[:api].create("files/#{apifid[:file_id]}/files",{name: new_folder,type: :folder})[:data]
318
+ return Main.result_status("created: #{result['name']} (id=#{result['id']})")
319
+ when :rename
320
+ thepath = options.get_next_argument('source path')
321
+ newname = options.get_next_argument('new name')
322
+ apifid = resolve_api_fid(top_file_id,thepath)
323
+ result = apifid[:api].update("files/#{apifid[:file_id]}",{name: newname})[:data]
324
+ return Main.result_status("renamed #{thepath} to #{newname}")
325
+ when :delete
326
+ thepath = options.get_next_argument('path')
327
+ return do_bulk_operation(thepath,'deleted','path') do |l_path|
328
+ raise "expecting String (path), got #{l_path.class.name} (#{l_path})" unless l_path.is_a?(String)
329
+ apifid = resolve_api_fid(top_file_id,l_path)
330
+ result = apifid[:api].delete("files/#{apifid[:file_id]}")[:data]
331
+ {'path' => l_path}
332
+ end
333
+ when :upload
334
+ apifid = resolve_api_fid(top_file_id,transfer.destination_folder(Fasp::TransferSpec::DIRECTION_SEND))
335
+ add_ts = {'tags' => {'aspera' => {'files' => {'parentCwd' => "#{apifid[:node_info]['id']}:#{apifid[:file_id]}"}}}}
336
+ return Main.result_transfer(transfer_start(AoC::FILES_APP,Fasp::TransferSpec::DIRECTION_SEND,apifid,add_ts))
337
+ when :download
338
+ source_paths = transfer.ts_source_paths
339
+ # special case for AoC : all files must be in same folder
340
+ source_folder = source_paths.shift['source']
341
+ # if a single file: split into folder and path
342
+ if source_paths.empty?
343
+ source_folder = source_folder.split(AoC::PATH_SEPARATOR)
344
+ source_paths = [{'source' => source_folder.pop}]
345
+ source_folder = source_folder.join(AoC::PATH_SEPARATOR)
346
+ end
347
+ apifid = resolve_api_fid(top_file_id,source_folder)
348
+ # override paths with just filename
349
+ add_ts = {'tags' => {'aspera' => {'files' => {'parentCwd' => "#{apifid[:node_info]['id']}:#{apifid[:file_id]}"}}}}
350
+ add_ts['paths'] = source_paths
351
+ return Main.result_transfer(transfer_start(AoC::FILES_APP,Fasp::TransferSpec::DIRECTION_RECEIVE,apifid,add_ts))
352
+ when :http_node_download
353
+ source_paths = transfer.ts_source_paths
354
+ source_folder = source_paths.shift['source']
355
+ if source_paths.empty?
356
+ source_folder = source_folder.split(AoC::PATH_SEPARATOR)
357
+ source_paths = [{'source' => source_folder.pop}]
358
+ source_folder = source_folder.join(AoC::PATH_SEPARATOR)
359
+ end
360
+ raise CliBadArgument,'one file at a time only in HTTP mode' if source_paths.length > 1
361
+ file_name = source_paths.first['source']
362
+ apifid = resolve_api_fid(top_file_id,File.join(source_folder,file_name))
363
+ apifid[:api].call(
364
+ operation: 'GET',
365
+ subpath: "files/#{apifid[:file_id]}/content",
366
+ save_to_file: File.join(transfer.destination_folder(Fasp::TransferSpec::DIRECTION_RECEIVE),file_name))
367
+ return Main.result_status("downloaded: #{file_name}")
368
+ when :permission
369
+ command_perm = options.get_next_command(%i[list create])
370
+ case command_perm
371
+ when :list
372
+ # generic options : TODO: as arg ? option_url_query
373
+ list_options ||= {'include' => ['[]','access_level','permission_count']}
374
+ # special value: ALL will show all permissions
375
+ if !VAL_ALL.eql?(apifid[:file_id])
376
+ # add which one to get
377
+ list_options['file_id'] = apifid[:file_id]
378
+ list_options['inherited'] ||= false
379
+ end
380
+ items = apifid[:api].read('permissions',list_options)[:data]
381
+ return {type: :object_list,data: items}
382
+ when :create
383
+ #create_param=self.options.get_next_argument('creation data (Hash)')
384
+ set_workspace_info
385
+ access_id = "#{ID_AK_ADMIN}_WS_#{@workspace_id}"
386
+ apifid[:node_info]
387
+ params = {
388
+ 'file_id' => apifid[:file_id], # mandatory
389
+ 'access_type' => 'user', # mandatory: user or group
390
+ 'access_id' => access_id, # id of user or group
391
+ 'access_levels' => Aspera::Node::ACCESS_LEVELS,
392
+ 'tags' => {'aspera' => {'files' => {'workspace' => {
393
+ 'id' => @workspace_id,
394
+ 'workspace_name' => @workspace_name,
395
+ 'user_name' => aoc_api.user_info['name'],
396
+ 'shared_by_user_id' => aoc_api.user_info['id'],
397
+ 'shared_by_name' => aoc_api.user_info['name'],
398
+ 'shared_by_email' => aoc_api.user_info['email'],
399
+ 'shared_with_name' => access_id,
400
+ 'access_key' => apifid[:node_info]['access_key'],
401
+ 'node' => apifid[:node_info]['name']}}}}}
402
+ item = apifid[:api].create('permissions',params)[:data]
403
+ return {type: :single_object,data: item}
404
+ else raise "internal error:shall not reach here (#{command_perm})"
405
+ end
406
+ when :file
407
+ command_node_file = options.get_next_command(%i[show modify])
408
+ file_path = options.get_option(:path)
409
+ apifid =
410
+ if !file_path.nil?
411
+ resolve_api_fid(top_file_id,file_path) # TODO: allow follow link ?
412
+ else
413
+ {node_info: top_file_id[:node_info],file_id: instance_identifier}
414
+ end
415
+ case command_node_file
416
+ when :show
417
+ items = apifid[:api].read("files/#{apifid[:file_id]}")[:data]
418
+ return {type: :single_object,data: items}
419
+ when :modify
420
+ update_param = options.get_next_argument('update data (Hash)')
421
+ res = apifid[:api].update("files/#{apifid[:file_id]}",update_param)[:data]
422
+ return {type: :single_object,data: res}
423
+ else raise "internal error:shall not reach here (#{command_node_file})"
424
+ end
425
+ end # command_repo
426
+ raise 'ERR'
427
+ end # execute_node_gen4_command
428
+
261
429
  def execute_async
262
- command=options.get_next_command([:list,:delete,:files,:show,:counters,:bandwidth])
430
+ command = options.get_next_command(%i[list delete files show counters bandwidth])
263
431
  unless command.eql?(:list)
264
- asyncname=options.get_option(:sync_name,:optional)
432
+ asyncname = options.get_option(:sync_name)
265
433
  if asyncname.nil?
266
- asyncid=instance_identifier()
267
- if asyncid.eql?('ALL') && [:show,:delete].include?(command)
268
- asyncids=@api_node.read('async/list')[:data]['sync_ids']
434
+ asyncid = instance_identifier
435
+ if asyncid.eql?('ALL') && %i[show delete].include?(command)
436
+ asyncids = @api_node.read('async/list')[:data]['sync_ids']
269
437
  else
270
438
  Integer(asyncid) # must be integer
271
- asyncids=[asyncid]
439
+ asyncids = [asyncid]
272
440
  end
273
441
  else
274
- asyncids=@api_node.read('async/list')[:data]['sync_ids']
275
- summaries=@api_node.create('async/summary',{'syncs' => asyncids})[:data]['sync_summaries']
276
- selected=summaries.select{|s|s['name'].eql?(asyncname)}.first
442
+ asyncids = @api_node.read('async/list')[:data]['sync_ids']
443
+ summaries = @api_node.create('async/summary',{'syncs' => asyncids})[:data]['sync_summaries']
444
+ selected = summaries.find{|s|s['name'].eql?(asyncname)}
277
445
  raise "no such sync: #{asyncname}" if selected.nil?
278
- asyncid=selected['snid']
279
- asyncids=[asyncid]
446
+ asyncid = selected['snid']
447
+ asyncids = [asyncid]
280
448
  end
281
- pdata={'syncs' => asyncids}
449
+ pdata = {'syncs' => asyncids}
282
450
  end
283
451
  case command
284
452
  when :list
285
- resp=@api_node.read('async/list')[:data]['sync_ids']
453
+ resp = @api_node.read('async/list')[:data]['sync_ids']
286
454
  return { type: :value_list, data: resp, name: 'id' }
287
455
  when :show
288
- resp=@api_node.create('async/summary',pdata)[:data]['sync_summaries']
456
+ resp = @api_node.create('async/summary',pdata)[:data]['sync_summaries']
289
457
  return Main.result_empty if resp.empty?
290
- return { type: :object_list, data: resp, fields: ['snid','name','local_dir','remote_dir'] } if asyncid.eql?('ALL')
458
+ return { type: :object_list, data: resp, fields: %w[snid name local_dir remote_dir] } if asyncid.eql?('ALL')
291
459
  return { type: :single_object, data: resp.first }
292
460
  when :delete
293
- resp=@api_node.create('async/delete',pdata)[:data]
461
+ resp = @api_node.create('async/delete',pdata)[:data]
294
462
  return { type: :single_object, data: resp, name: 'id' }
295
463
  when :bandwidth
296
- pdata['seconds']=100 # TODO: as parameter with --value
297
- resp=@api_node.create('async/bandwidth',pdata)[:data]
298
- data=resp['bandwidth_data']
464
+ pdata['seconds'] = 100 # TODO: as parameter with --value
465
+ resp = @api_node.create('async/bandwidth',pdata)[:data]
466
+ data = resp['bandwidth_data']
299
467
  return Main.result_empty if data.empty?
300
- data=data.first[asyncid]['data']
468
+ data = data.first[asyncid]['data']
301
469
  return { type: :object_list, data: data, name: 'id' }
302
470
  when :files
303
471
  # count int
304
472
  # filename str
305
473
  # skip int
306
474
  # status int
307
- filter=options.get_option(:value,:optional)
475
+ filter = options.get_option(:value)
308
476
  pdata.merge!(filter) unless filter.nil?
309
- resp=@api_node.create('async/files',pdata)[:data]
310
- data=resp['sync_files']
311
- data=data.first[asyncid] unless data.empty?
312
- iteration_data=[]
313
- skip_ids_persistency=nil
314
- if options.get_option(:once_only,:mandatory)
315
- skip_ids_persistency=PersistencyActionOnce.new(
316
- manager: @agents[:persistency],
317
- data: iteration_data,
318
- id: IdGenerator.from_list(['sync_files',options.get_option(:url,:mandatory),options.get_option(:username,:mandatory),asyncid]))
477
+ resp = @api_node.create('async/files',pdata)[:data]
478
+ data = resp['sync_files']
479
+ data = data.first[asyncid] unless data.empty?
480
+ iteration_data = []
481
+ skip_ids_persistency = nil
482
+ if options.get_option(:once_only,is_type: :mandatory)
483
+ skip_ids_persistency = PersistencyActionOnce.new(
484
+ manager: @agents[:persistency],
485
+ data: iteration_data,
486
+ id: IdGenerator.from_list([
487
+ 'sync_files',
488
+ options.get_option(:url,is_type: :mandatory),
489
+ options.get_option(:username,is_type: :mandatory),
490
+ asyncid]))
319
491
  unless iteration_data.first.nil?
320
- data.select!{|l| l['fnid'].to_i>iteration_data.first}
492
+ data.select!{|l| l['fnid'].to_i > iteration_data.first}
321
493
  end
322
- iteration_data[0]=data.last['fnid'].to_i unless data.empty?
494
+ iteration_data[0] = data.last['fnid'].to_i unless data.empty?
323
495
  end
324
496
  return Main.result_empty if data.empty?
325
- skip_ids_persistency.save unless skip_ids_persistency.nil?
497
+ skip_ids_persistency&.save
326
498
  return { type: :object_list, data: data, name: 'id' }
327
499
  when :counters
328
- resp=@api_node.create('async/counters',pdata)[:data]['sync_counters'].first[asyncid].last
500
+ resp = @api_node.create('async/counters',pdata)[:data]['sync_counters'].first[asyncid].last
329
501
  return Main.result_empty if resp.nil?
330
502
  return { type: :single_object, data: resp }
331
503
  end
332
504
  end
333
505
 
334
- ACTIONS=[:postprocess,:stream, :transfer, :cleanup, :forward, :access_key, :watch_folder, :service, :async, :central, :asperabrowser, :basic_token].concat(COMMON_ACTIONS)
506
+ ACTIONS = %i[postprocess stream transfer cleanup forward access_key watch_folder service async central asperabrowser basic_token].concat(COMMON_ACTIONS).freeze
335
507
 
336
508
  def execute_action(command=nil,prefix_path=nil)
337
- command||=options.get_next_command(ACTIONS)
509
+ command ||= options.get_next_command(ACTIONS)
338
510
  case command
339
511
  when *COMMON_ACTIONS then return execute_simple_common(command,prefix_path)
340
- when :async then return execute_async()
512
+ when :async then return execute_async
341
513
  when :stream
342
- command=options.get_next_command([:list, :create, :show, :modify, :cancel])
514
+ command = options.get_next_command(%i[list create show modify cancel])
343
515
  case command
344
516
  when :list
345
- resp=@api_node.read('ops/transfers',options.get_option(:value,:optional))
346
- return { type: :object_list, data: resp[:data], fields: ['id','status'] } # TODO: useful?
517
+ resp = @api_node.read('ops/transfers',options.get_option(:value))
518
+ return { type: :object_list, data: resp[:data], fields: %w[id status] } # TODO: useful?
347
519
  when :create
348
- resp=@api_node.create('streams',options.get_option(:value,:mandatory))
520
+ resp = @api_node.create('streams',options.get_option(:value,is_type: :mandatory))
349
521
  return { type: :single_object, data: resp[:data] }
350
522
  when :show
351
- trid=options.get_next_argument('transfer id')
352
- resp=@api_node.read('ops/transfers/'+trid)
523
+ trid = options.get_next_argument('transfer id')
524
+ resp = @api_node.read('ops/transfers/' + trid)
353
525
  return { type: :other_struct, data: resp[:data] }
354
526
  when :modify
355
- trid=options.get_next_argument('transfer id')
356
- resp=@api_node.update('streams/'+trid,options.get_option(:value,:mandatory))
527
+ trid = options.get_next_argument('transfer id')
528
+ resp = @api_node.update('streams/' + trid,options.get_option(:value,is_type: :mandatory))
357
529
  return { type: :other_struct, data: resp[:data] }
358
530
  when :cancel
359
- trid=options.get_next_argument('transfer id')
360
- resp=@api_node.cancel('streams/'+trid)
531
+ trid = options.get_next_argument('transfer id')
532
+ resp = @api_node.cancel('streams/' + trid)
361
533
  return { type: :other_struct, data: resp[:data] }
362
534
  else
363
535
  raise 'error'
364
536
  end
365
537
  when :transfer
366
- command=options.get_next_command([:list, :cancel, :show])
367
- res_class_path='ops/transfers'
368
- if [:cancel, :show].include?(command)
369
- one_res_id=instance_identifier()
370
- one_res_path="#{res_class_path}/#{one_res_id}"
538
+ command = options.get_next_command(%i[list cancel show])
539
+ res_class_path = 'ops/transfers'
540
+ if %i[cancel show].include?(command)
541
+ one_res_id = instance_identifier
542
+ one_res_path = "#{res_class_path}/#{one_res_id}"
371
543
  end
372
544
  case command
373
545
  when :list
374
546
  # could use ? subpath: 'transfers'
375
- resp=@api_node.read(res_class_path,options.get_option(:value,:optional))
376
- return { type: :object_list, data: resp[:data],
377
- fields: ['id','status','start_spec.direction','start_spec.remote_user','start_spec.remote_host','start_spec.destination_path']}
547
+ resp = @api_node.read(res_class_path,options.get_option(:value))
548
+ return {
549
+ type: :object_list,
550
+ data: resp[:data],
551
+ fields: %w[id status start_spec.direction start_spec.remote_user start_spec.remote_host start_spec.destination_path]
552
+ }
378
553
  when :cancel
379
- resp=@api_node.cancel(one_res_path)
554
+ resp = @api_node.cancel(one_res_path)
380
555
  return { type: :other_struct, data: resp[:data] }
381
556
  when :show
382
- resp=@api_node.read(one_res_path)
557
+ resp = @api_node.read(one_res_path)
383
558
  return { type: :other_struct, data: resp[:data] }
384
559
  else
385
560
  raise 'error'
386
561
  end
387
562
  when :access_key
388
- return entity_action(@api_node,'access_keys',id_default: 'self')
563
+ ak_command = options.get_next_command([Plugin::ALL_OPS,:do].flatten)
564
+ case ak_command
565
+ when *Plugin::ALL_OPS then return entity_command(ak_command,@api_node,'access_keys',id_default: 'self')
566
+ when :do
567
+ access_key = options.get_next_argument('access key id')
568
+ ak_info=@api_node.read("access_keys/#{access_key}")[:data]
569
+ # change API if needed
570
+ if !access_key.eql?('self')
571
+ secret=config.vault.get(username: access_key)[:secret] #, url: @api_node.params[:base_url] : TODO: better handle vault
572
+ @api_node.params[:username]=access_key
573
+ @api_node.params[:password]=secret
574
+ end
575
+ command_repo = options.get_next_command(NODE4_COMMANDS)
576
+ return execute_node_gen4_command(command_repo,ak_info['root_file_id'])
577
+ end
389
578
  when :service
390
- command=options.get_next_command([:list, :create, :delete])
579
+ command = options.get_next_command(%i[list create delete])
391
580
  if [:delete].include?(command)
392
- svcid=instance_identifier()
581
+ svcid = instance_identifier
393
582
  end
394
583
  case command
395
584
  when :list
396
- resp=@api_node.read('rund/services')
585
+ resp = @api_node.read('rund/services')
397
586
  return { type: :object_list, data: resp[:data]['services'] }
398
587
  when :create
399
588
  # @json:'{"type":"WATCHFOLDERD","run_as":{"user":"user1"}}'
400
- params=options.get_next_argument('Run creation data (structure)')
401
- resp=@api_node.create('rund/services',params)
589
+ params = options.get_next_argument('Run creation data (structure)')
590
+ resp = @api_node.create('rund/services',params)
402
591
  return Main.result_status("#{resp[:data]['id']} created")
403
592
  when :delete
404
593
  @api_node.delete("rund/services/#{svcid}")
405
594
  return Main.result_status("#{svcid} deleted")
406
595
  end
407
596
  when :watch_folder
408
- res_class_path='v3/watchfolders'
409
- command=options.get_next_command([:create, :list, :show, :modify, :delete, :state])
410
- if [:show,:modify,:delete,:state].include?(command)
411
- one_res_id=instance_identifier()
412
- one_res_path="#{res_class_path}/#{one_res_id}"
597
+ res_class_path = 'v3/watchfolders'
598
+ command = options.get_next_command(%i[create list show modify delete state])
599
+ if %i[show modify delete state].include?(command)
600
+ one_res_id = instance_identifier
601
+ one_res_path = "#{res_class_path}/#{one_res_id}"
413
602
  end
414
603
  # hum, to avoid: Unable to convert 2016_09_14 configuration
415
- @api_node.params[:headers]||={}
416
- @api_node.params[:headers]['X-aspera-WF-version']='2017_10_23'
604
+ @api_node.params[:headers] ||= {}
605
+ @api_node.params[:headers]['X-aspera-WF-version'] = '2017_10_23'
417
606
  case command
418
607
  when :create
419
- resp=@api_node.create(res_class_path,options.get_option(:value,:mandatory))
608
+ resp = @api_node.create(res_class_path,options.get_option(:value,is_type: :mandatory))
420
609
  return Main.result_status("#{resp[:data]['id']} created")
421
610
  when :list
422
- resp=@api_node.read(res_class_path,options.get_option(:value,:optional))
611
+ resp = @api_node.read(res_class_path,options.get_option(:value))
423
612
  return { type: :value_list, data: resp[:data]['ids'], name: 'id' }
424
613
  when :show
425
614
  return { type: :single_object, data: @api_node.read(one_res_path)[:data]}
426
615
  when :modify
427
- @api_node.update(one_res_path,options.get_option(:value,:mandatory))
616
+ @api_node.update(one_res_path,options.get_option(:value,is_type: :mandatory))
428
617
  return Main.result_status("#{one_res_id} updated")
429
618
  when :delete
430
619
  @api_node.delete(one_res_path)
@@ -433,30 +622,30 @@ fields: ['id','status','start_spec.direction','start_spec.remote_user','start_sp
433
622
  return { type: :single_object, data: @api_node.read("#{one_res_path}/state")[:data] }
434
623
  end
435
624
  when :central
436
- command=options.get_next_command([:session,:file])
437
- validator_id=options.get_option(:validator)
438
- validation={'validator_id'=>validator_id} unless validator_id.nil?
439
- request_data=options.get_option(:value,:optional)
440
- request_data||={}
625
+ command = options.get_next_command(%i[session file])
626
+ validator_id = options.get_option(:validator)
627
+ validation = {'validator_id' => validator_id} unless validator_id.nil?
628
+ request_data = options.get_option(:value)
629
+ request_data ||= {}
441
630
  case command
442
631
  when :session
443
- command=options.get_next_command([:list])
632
+ command = options.get_next_command([:list])
444
633
  case command
445
634
  when :list
446
- request_data.deep_merge!({'validation'=>validation}) unless validation.nil?
447
- resp=@api_node.create('services/rest/transfers/v1/sessions',request_data)
635
+ request_data.deep_merge!({'validation' => validation}) unless validation.nil?
636
+ resp = @api_node.create('services/rest/transfers/v1/sessions',request_data)
448
637
  return { type: :object_list, data: resp[:data]['session_info_result']['session_info'],
449
- fields: ['session_uuid','status','transport','direction','bytes_transferred']}
638
+ fields: %w[session_uuid status transport direction bytes_transferred]}
450
639
  end
451
640
  when :file
452
- command=options.get_next_command([:list, :modify])
641
+ command = options.get_next_command(%i[list modify])
453
642
  case command
454
643
  when :list
455
- request_data.deep_merge!({'validation'=>validation}) unless validation.nil?
456
- resp=@api_node.create('services/rest/transfers/v1/files',request_data)[:data]
457
- resp=JSON.parse(resp) if resp.is_a?(String)
644
+ request_data.deep_merge!({'validation' => validation}) unless validation.nil?
645
+ resp = @api_node.create('services/rest/transfers/v1/files',request_data)[:data]
646
+ resp = JSON.parse(resp) if resp.is_a?(String)
458
647
  Log.dump(:resp,resp)
459
- return { type: :object_list, data: resp['file_transfer_info_result']['file_transfer_info'], fields: ['session_uuid','file_id','status','path']}
648
+ return { type: :object_list, data: resp['file_transfer_info_result']['file_transfer_info'], fields: %w[session_uuid file_id status path]}
460
649
  when :modify
461
650
  request_data.deep_merge!(validation) unless validation.nil?
462
651
  @api_node.update('services/rest/transfers/v1/files',request_data)
@@ -464,17 +653,17 @@ fields: ['session_uuid','status','transport','direction','bytes_transferred']}
464
653
  end
465
654
  end
466
655
  when :asperabrowser
467
- browse_params={
468
- 'nodeUser' => options.get_option(:username,:mandatory),
469
- 'nodePW' => options.get_option(:password,:mandatory),
470
- 'nodeURL' => options.get_option(:url,:mandatory)
656
+ browse_params = {
657
+ 'nodeUser' => options.get_option(:username,is_type: :mandatory),
658
+ 'nodePW' => options.get_option(:password,is_type: :mandatory),
659
+ 'nodeURL' => options.get_option(:url,is_type: :mandatory)
471
660
  }
472
661
  # encode parameters so that it looks good in url
473
- encoded_params=Base64.strict_encode64(Zlib::Deflate.deflate(JSON.generate(browse_params))).gsub(/=+$/, '').tr('+/', '-_').reverse
474
- OpenApplication.instance.uri(options.get_option(:asperabrowserurl)+'?goto='+encoded_params)
662
+ encoded_params = Base64.strict_encode64(Zlib::Deflate.deflate(JSON.generate(browse_params))).gsub(/=+$/, '').tr('+/', '-_').reverse
663
+ OpenApplication.instance.uri(options.get_option(:asperabrowserurl) + '?goto=' + encoded_params)
475
664
  return Main.result_status('done')
476
665
  when :basic_token
477
- return Main.result_status('Basic '+Base64.strict_encode64("#{options.get_option(:username,:mandatory)}:#{options.get_option(:password,:mandatory)}"))
666
+ return Main.result_status(Rest.basic_creds(options.get_option(:username,is_type: :mandatory),options.get_option(:password,is_type: :mandatory)))
478
667
  end # case command
479
668
  raise 'ERROR: shall not reach this line'
480
669
  end # execute_action