aspera-cli 4.7.0 → 4.9.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 (96) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +1267 -999
  4. data/bin/ascli +20 -1
  5. data/bin/asession +37 -34
  6. data/docs/test_env.conf +7 -3
  7. data/examples/aoc.rb +13 -12
  8. data/examples/dascli +23 -0
  9. data/examples/faspex4.rb +34 -29
  10. data/examples/{transfer.rb → node.rb} +31 -59
  11. data/examples/server.rb +93 -0
  12. data/lib/aspera/aoc.rb +153 -143
  13. data/lib/aspera/ascmd.rb +56 -45
  14. data/lib/aspera/ats_api.rb +9 -6
  15. data/lib/aspera/cli/basic_auth_plugin.rb +18 -16
  16. data/lib/aspera/cli/extended_value.rb +33 -30
  17. data/lib/aspera/cli/formater.rb +105 -111
  18. data/lib/aspera/cli/info.rb +3 -2
  19. data/lib/aspera/cli/listener/line_dump.rb +1 -0
  20. data/lib/aspera/cli/listener/logger.rb +1 -0
  21. data/lib/aspera/cli/listener/progress.rb +13 -12
  22. data/lib/aspera/cli/listener/progress_multi.rb +21 -20
  23. data/lib/aspera/cli/main.rb +110 -90
  24. data/lib/aspera/cli/manager.rb +99 -88
  25. data/lib/aspera/cli/plugin.rb +98 -39
  26. data/lib/aspera/cli/plugins/alee.rb +6 -5
  27. data/lib/aspera/cli/plugins/aoc.rb +581 -450
  28. data/lib/aspera/cli/plugins/ats.rb +84 -83
  29. data/lib/aspera/cli/plugins/bss.rb +30 -27
  30. data/lib/aspera/cli/plugins/config.rb +488 -397
  31. data/lib/aspera/cli/plugins/console.rb +17 -15
  32. data/lib/aspera/cli/plugins/cos.rb +26 -35
  33. data/lib/aspera/cli/plugins/faspex.rb +206 -172
  34. data/lib/aspera/cli/plugins/faspex5.rb +109 -74
  35. data/lib/aspera/cli/plugins/node.rb +379 -189
  36. data/lib/aspera/cli/plugins/orchestrator.rb +71 -65
  37. data/lib/aspera/cli/plugins/preview.rb +131 -122
  38. data/lib/aspera/cli/plugins/server.rb +50 -150
  39. data/lib/aspera/cli/plugins/shares.rb +61 -27
  40. data/lib/aspera/cli/plugins/sync.rb +15 -14
  41. data/lib/aspera/cli/transfer_agent.rb +75 -64
  42. data/lib/aspera/cli/version.rb +2 -1
  43. data/lib/aspera/colors.rb +29 -28
  44. data/lib/aspera/command_line_builder.rb +50 -43
  45. data/lib/aspera/cos_node.rb +64 -38
  46. data/lib/aspera/data_repository.rb +1 -0
  47. data/lib/aspera/environment.rb +33 -10
  48. data/lib/aspera/fasp/agent_base.rb +35 -30
  49. data/lib/aspera/fasp/agent_connect.rb +35 -30
  50. data/lib/aspera/fasp/agent_direct.rb +68 -60
  51. data/lib/aspera/fasp/agent_httpgw.rb +71 -64
  52. data/lib/aspera/fasp/agent_node.rb +24 -23
  53. data/lib/aspera/fasp/agent_trsdk.rb +19 -20
  54. data/lib/aspera/fasp/error.rb +2 -1
  55. data/lib/aspera/fasp/error_info.rb +79 -68
  56. data/lib/aspera/fasp/installation.rb +130 -126
  57. data/lib/aspera/fasp/listener.rb +1 -0
  58. data/lib/aspera/fasp/parameters.rb +71 -60
  59. data/lib/aspera/fasp/parameters.yaml +69 -17
  60. data/lib/aspera/fasp/resume_policy.rb +14 -11
  61. data/lib/aspera/fasp/transfer_spec.rb +6 -5
  62. data/lib/aspera/fasp/uri.rb +25 -24
  63. data/lib/aspera/faspex_gw.rb +83 -72
  64. data/lib/aspera/hash_ext.rb +23 -13
  65. data/lib/aspera/id_generator.rb +16 -13
  66. data/lib/aspera/keychain/encrypted_hash.rb +61 -46
  67. data/lib/aspera/keychain/macos_security.rb +26 -24
  68. data/lib/aspera/log.rb +35 -39
  69. data/lib/aspera/nagios.rb +36 -28
  70. data/lib/aspera/node.rb +19 -19
  71. data/lib/aspera/oauth.rb +120 -100
  72. data/lib/aspera/open_application.rb +25 -22
  73. data/lib/aspera/persistency_action_once.rb +9 -8
  74. data/lib/aspera/persistency_folder.rb +13 -9
  75. data/lib/aspera/preview/file_types.rb +261 -266
  76. data/lib/aspera/preview/generator.rb +74 -73
  77. data/lib/aspera/preview/image_error.png +0 -0
  78. data/lib/aspera/preview/options.rb +7 -6
  79. data/lib/aspera/preview/utils.rb +30 -33
  80. data/lib/aspera/preview/video_error.png +0 -0
  81. data/lib/aspera/proxy_auto_config.rb +27 -23
  82. data/lib/aspera/rest.rb +73 -74
  83. data/lib/aspera/rest_call_error.rb +1 -0
  84. data/lib/aspera/rest_error_analyzer.rb +23 -19
  85. data/lib/aspera/rest_errors_aspera.rb +43 -40
  86. data/lib/aspera/secret_hider.rb +74 -0
  87. data/lib/aspera/ssh.rb +13 -10
  88. data/lib/aspera/sync.rb +49 -47
  89. data/lib/aspera/temp_file_manager.rb +7 -5
  90. data/lib/aspera/timer_limiter.rb +9 -8
  91. data/lib/aspera/uri_reader.rb +17 -18
  92. data/lib/aspera/web_auth.rb +17 -15
  93. data.tar.gz.sig +5 -0
  94. metadata +119 -35
  95. metadata.gz.sig +0 -0
  96. 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,353 @@ 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
+ Log.log.debug("TODO #{path}")
278
+ return {api: @api_node, file_id: id}
279
+ end
280
+
281
+ NODE4_COMMANDS = %i[browse find mkdir rename delete upload download http_node_download file permission bearer_token_node node_info].freeze
282
+
283
+ def execute_node_gen4_command(command_repo, top_file_id)
284
+ #@api_node
285
+ case command_repo
286
+ when :node_info
287
+ thepath = options.get_next_argument('path')
288
+ apifid = resolve_api_fid(top_file_id,thepath)
289
+ apifid[:api] = aoc_api.get_node_api(apifid[:node_info], use_secret: false)
290
+ return {type: :single_object,data: {
291
+ url: apifid[:node_info]['url'],
292
+ username: apifid[:node_info]['access_key'],
293
+ password: apifid[:api].oauth_token,
294
+ root_id: apifid[:file_id]
295
+ }}
296
+ when :browse
297
+ thepath = options.get_next_argument('path')
298
+ apifid = resolve_api_fid(top_file_id,thepath)
299
+ file_info = apifid[:api].read("files/#{apifid[:file_id]}")[:data]
300
+ if file_info['type'].eql?('folder')
301
+ result = apifid[:api].read("files/#{apifid[:file_id]}/files",options.get_option(:value))
302
+ items = result[:data]
303
+ self.format.display_status("Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}")
304
+ else
305
+ items = [file_info]
306
+ end
307
+ return {type: :object_list,data: items,fields: %w[name type recursive_size size modified_time access_level]}
308
+ when :find
309
+ thepath = options.get_next_argument('path')
310
+ apifid = resolve_api_fid(top_file_id,thepath)
311
+ test_block = Aspera::Node.file_matcher(options.get_option(:value))
312
+ return {type: :object_list,data: aoc_api.find_files(apifid,test_block),fields: ['path']}
313
+ when :mkdir
314
+ thepath = options.get_next_argument('path')
315
+ containing_folder_path = thepath.split(AoC::PATH_SEPARATOR)
316
+ new_folder = containing_folder_path.pop
317
+ apifid = resolve_api_fid(top_file_id,containing_folder_path.join(AoC::PATH_SEPARATOR))
318
+ result = apifid[:api].create("files/#{apifid[:file_id]}/files",{name: new_folder,type: :folder})[:data]
319
+ return Main.result_status("created: #{result['name']} (id=#{result['id']})")
320
+ when :rename
321
+ thepath = options.get_next_argument('source path')
322
+ newname = options.get_next_argument('new name')
323
+ apifid = resolve_api_fid(top_file_id,thepath)
324
+ result = apifid[:api].update("files/#{apifid[:file_id]}",{name: newname})[:data]
325
+ return Main.result_status("renamed #{thepath} to #{newname}")
326
+ when :delete
327
+ thepath = options.get_next_argument('path')
328
+ return do_bulk_operation(thepath,'deleted','path') do |l_path|
329
+ raise "expecting String (path), got #{l_path.class.name} (#{l_path})" unless l_path.is_a?(String)
330
+ apifid = resolve_api_fid(top_file_id,l_path)
331
+ result = apifid[:api].delete("files/#{apifid[:file_id]}")[:data]
332
+ {'path' => l_path}
333
+ end
334
+ when :upload
335
+ apifid = resolve_api_fid(top_file_id,transfer.destination_folder(Fasp::TransferSpec::DIRECTION_SEND))
336
+ add_ts = {'tags' => {'aspera' => {'files' => {'parentCwd' => "#{apifid[:node_info]['id']}:#{apifid[:file_id]}"}}}}
337
+ return Main.result_transfer(transfer_start(AoC::FILES_APP,Fasp::TransferSpec::DIRECTION_SEND,apifid,add_ts))
338
+ when :download
339
+ source_paths = transfer.ts_source_paths
340
+ # special case for AoC : all files must be in same folder
341
+ source_folder = source_paths.shift['source']
342
+ # if a single file: split into folder and path
343
+ if source_paths.empty?
344
+ source_folder = source_folder.split(AoC::PATH_SEPARATOR)
345
+ source_paths = [{'source' => source_folder.pop}]
346
+ source_folder = source_folder.join(AoC::PATH_SEPARATOR)
347
+ end
348
+ apifid = resolve_api_fid(top_file_id,source_folder)
349
+ # override paths with just filename
350
+ add_ts = {'tags' => {'aspera' => {'files' => {'parentCwd' => "#{apifid[:node_info]['id']}:#{apifid[:file_id]}"}}}}
351
+ add_ts['paths'] = source_paths
352
+ return Main.result_transfer(transfer_start(AoC::FILES_APP,Fasp::TransferSpec::DIRECTION_RECEIVE,apifid,add_ts))
353
+ when :http_node_download
354
+ source_paths = transfer.ts_source_paths
355
+ source_folder = source_paths.shift['source']
356
+ if source_paths.empty?
357
+ source_folder = source_folder.split(AoC::PATH_SEPARATOR)
358
+ source_paths = [{'source' => source_folder.pop}]
359
+ source_folder = source_folder.join(AoC::PATH_SEPARATOR)
360
+ end
361
+ raise CliBadArgument,'one file at a time only in HTTP mode' if source_paths.length > 1
362
+ file_name = source_paths.first['source']
363
+ apifid = resolve_api_fid(top_file_id,File.join(source_folder,file_name))
364
+ apifid[:api].call(
365
+ operation: 'GET',
366
+ subpath: "files/#{apifid[:file_id]}/content",
367
+ save_to_file: File.join(transfer.destination_folder(Fasp::TransferSpec::DIRECTION_RECEIVE),file_name))
368
+ return Main.result_status("downloaded: #{file_name}")
369
+ when :permission
370
+ command_perm = options.get_next_command(%i[list create])
371
+ case command_perm
372
+ when :list
373
+ # generic options : TODO: as arg ? option_url_query
374
+ list_options ||= {'include' => ['[]','access_level','permission_count']}
375
+ # special value: ALL will show all permissions
376
+ if !VAL_ALL.eql?(apifid[:file_id])
377
+ # add which one to get
378
+ list_options['file_id'] = apifid[:file_id]
379
+ list_options['inherited'] ||= false
380
+ end
381
+ items = apifid[:api].read('permissions',list_options)[:data]
382
+ return {type: :object_list,data: items}
383
+ when :create
384
+ #create_param=self.options.get_next_argument('creation data (Hash)')
385
+ set_workspace_info
386
+ access_id = "#{ID_AK_ADMIN}_WS_#{@workspace_id}"
387
+ apifid[:node_info]
388
+ params = {
389
+ 'file_id' => apifid[:file_id], # mandatory
390
+ 'access_type' => 'user', # mandatory: user or group
391
+ 'access_id' => access_id, # id of user or group
392
+ 'access_levels' => Aspera::Node::ACCESS_LEVELS,
393
+ 'tags' => {'aspera' => {'files' => {'workspace' => {
394
+ 'id' => @workspace_id,
395
+ 'workspace_name' => @workspace_name,
396
+ 'user_name' => aoc_api.user_info['name'],
397
+ 'shared_by_user_id' => aoc_api.user_info['id'],
398
+ 'shared_by_name' => aoc_api.user_info['name'],
399
+ 'shared_by_email' => aoc_api.user_info['email'],
400
+ 'shared_with_name' => access_id,
401
+ 'access_key' => apifid[:node_info]['access_key'],
402
+ 'node' => apifid[:node_info]['name']}}}}}
403
+ item = apifid[:api].create('permissions',params)[:data]
404
+ return {type: :single_object,data: item}
405
+ else raise "internal error:shall not reach here (#{command_perm})"
406
+ end
407
+ when :file
408
+ command_node_file = options.get_next_command(%i[show modify])
409
+ file_path = options.get_option(:path)
410
+ apifid =
411
+ if !file_path.nil?
412
+ resolve_api_fid(top_file_id,file_path) # TODO: allow follow link ?
413
+ else
414
+ {node_info: top_file_id[:node_info],file_id: instance_identifier}
415
+ end
416
+ case command_node_file
417
+ when :show
418
+ items = apifid[:api].read("files/#{apifid[:file_id]}")[:data]
419
+ return {type: :single_object,data: items}
420
+ when :modify
421
+ update_param = options.get_next_argument('update data (Hash)')
422
+ res = apifid[:api].update("files/#{apifid[:file_id]}",update_param)[:data]
423
+ return {type: :single_object,data: res}
424
+ else raise "internal error:shall not reach here (#{command_node_file})"
425
+ end
426
+ end # command_repo
427
+ raise 'ERR'
428
+ end # execute_node_gen4_command
429
+
261
430
  def execute_async
262
- command=options.get_next_command([:list,:delete,:files,:show,:counters,:bandwidth])
431
+ command = options.get_next_command(%i[list delete files show counters bandwidth])
263
432
  unless command.eql?(:list)
264
- asyncname=options.get_option(:sync_name,:optional)
433
+ asyncname = options.get_option(:sync_name)
265
434
  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']
435
+ asyncid = instance_identifier
436
+ if asyncid.eql?('ALL') && %i[show delete].include?(command)
437
+ asyncids = @api_node.read('async/list')[:data]['sync_ids']
269
438
  else
270
439
  Integer(asyncid) # must be integer
271
- asyncids=[asyncid]
440
+ asyncids = [asyncid]
272
441
  end
273
442
  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
443
+ asyncids = @api_node.read('async/list')[:data]['sync_ids']
444
+ summaries = @api_node.create('async/summary',{'syncs' => asyncids})[:data]['sync_summaries']
445
+ selected = summaries.find{|s|s['name'].eql?(asyncname)}
277
446
  raise "no such sync: #{asyncname}" if selected.nil?
278
- asyncid=selected['snid']
279
- asyncids=[asyncid]
447
+ asyncid = selected['snid']
448
+ asyncids = [asyncid]
280
449
  end
281
- pdata={'syncs' => asyncids}
450
+ pdata = {'syncs' => asyncids}
282
451
  end
283
452
  case command
284
453
  when :list
285
- resp=@api_node.read('async/list')[:data]['sync_ids']
454
+ resp = @api_node.read('async/list')[:data]['sync_ids']
286
455
  return { type: :value_list, data: resp, name: 'id' }
287
456
  when :show
288
- resp=@api_node.create('async/summary',pdata)[:data]['sync_summaries']
457
+ resp = @api_node.create('async/summary',pdata)[:data]['sync_summaries']
289
458
  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')
459
+ return { type: :object_list, data: resp, fields: %w[snid name local_dir remote_dir] } if asyncid.eql?('ALL')
291
460
  return { type: :single_object, data: resp.first }
292
461
  when :delete
293
- resp=@api_node.create('async/delete',pdata)[:data]
462
+ resp = @api_node.create('async/delete',pdata)[:data]
294
463
  return { type: :single_object, data: resp, name: 'id' }
295
464
  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']
465
+ pdata['seconds'] = 100 # TODO: as parameter with --value
466
+ resp = @api_node.create('async/bandwidth',pdata)[:data]
467
+ data = resp['bandwidth_data']
299
468
  return Main.result_empty if data.empty?
300
- data=data.first[asyncid]['data']
469
+ data = data.first[asyncid]['data']
301
470
  return { type: :object_list, data: data, name: 'id' }
302
471
  when :files
303
472
  # count int
304
473
  # filename str
305
474
  # skip int
306
475
  # status int
307
- filter=options.get_option(:value,:optional)
476
+ filter = options.get_option(:value)
308
477
  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]))
478
+ resp = @api_node.create('async/files',pdata)[:data]
479
+ data = resp['sync_files']
480
+ data = data.first[asyncid] unless data.empty?
481
+ iteration_data = []
482
+ skip_ids_persistency = nil
483
+ if options.get_option(:once_only,is_type: :mandatory)
484
+ skip_ids_persistency = PersistencyActionOnce.new(
485
+ manager: @agents[:persistency],
486
+ data: iteration_data,
487
+ id: IdGenerator.from_list([
488
+ 'sync_files',
489
+ options.get_option(:url,is_type: :mandatory),
490
+ options.get_option(:username,is_type: :mandatory),
491
+ asyncid]))
319
492
  unless iteration_data.first.nil?
320
- data.select!{|l| l['fnid'].to_i>iteration_data.first}
493
+ data.select!{|l| l['fnid'].to_i > iteration_data.first}
321
494
  end
322
- iteration_data[0]=data.last['fnid'].to_i unless data.empty?
495
+ iteration_data[0] = data.last['fnid'].to_i unless data.empty?
323
496
  end
324
497
  return Main.result_empty if data.empty?
325
- skip_ids_persistency.save unless skip_ids_persistency.nil?
498
+ skip_ids_persistency&.save
326
499
  return { type: :object_list, data: data, name: 'id' }
327
500
  when :counters
328
- resp=@api_node.create('async/counters',pdata)[:data]['sync_counters'].first[asyncid].last
501
+ resp = @api_node.create('async/counters',pdata)[:data]['sync_counters'].first[asyncid].last
329
502
  return Main.result_empty if resp.nil?
330
503
  return { type: :single_object, data: resp }
331
504
  end
332
505
  end
333
506
 
334
- ACTIONS=[:postprocess,:stream, :transfer, :cleanup, :forward, :access_key, :watch_folder, :service, :async, :central, :asperabrowser, :basic_token].concat(COMMON_ACTIONS)
507
+ ACTIONS = %i[postprocess stream transfer cleanup forward access_key watch_folder service async central asperabrowser basic_token].concat(COMMON_ACTIONS).freeze
335
508
 
336
509
  def execute_action(command=nil,prefix_path=nil)
337
- command||=options.get_next_command(ACTIONS)
510
+ command ||= options.get_next_command(ACTIONS)
338
511
  case command
339
512
  when *COMMON_ACTIONS then return execute_simple_common(command,prefix_path)
340
- when :async then return execute_async()
513
+ when :async then return execute_async
341
514
  when :stream
342
- command=options.get_next_command([:list, :create, :show, :modify, :cancel])
515
+ command = options.get_next_command(%i[list create show modify cancel])
343
516
  case command
344
517
  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?
518
+ resp = @api_node.read('ops/transfers',options.get_option(:value))
519
+ return { type: :object_list, data: resp[:data], fields: %w[id status] } # TODO: useful?
347
520
  when :create
348
- resp=@api_node.create('streams',options.get_option(:value,:mandatory))
521
+ resp = @api_node.create('streams',options.get_option(:value,is_type: :mandatory))
349
522
  return { type: :single_object, data: resp[:data] }
350
523
  when :show
351
- trid=options.get_next_argument('transfer id')
352
- resp=@api_node.read('ops/transfers/'+trid)
524
+ trid = options.get_next_argument('transfer id')
525
+ resp = @api_node.read('ops/transfers/' + trid)
353
526
  return { type: :other_struct, data: resp[:data] }
354
527
  when :modify
355
- trid=options.get_next_argument('transfer id')
356
- resp=@api_node.update('streams/'+trid,options.get_option(:value,:mandatory))
528
+ trid = options.get_next_argument('transfer id')
529
+ resp = @api_node.update('streams/' + trid,options.get_option(:value,is_type: :mandatory))
357
530
  return { type: :other_struct, data: resp[:data] }
358
531
  when :cancel
359
- trid=options.get_next_argument('transfer id')
360
- resp=@api_node.cancel('streams/'+trid)
532
+ trid = options.get_next_argument('transfer id')
533
+ resp = @api_node.cancel('streams/' + trid)
361
534
  return { type: :other_struct, data: resp[:data] }
362
535
  else
363
536
  raise 'error'
364
537
  end
365
538
  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}"
539
+ command = options.get_next_command(%i[list cancel show])
540
+ res_class_path = 'ops/transfers'
541
+ if %i[cancel show].include?(command)
542
+ one_res_id = instance_identifier
543
+ one_res_path = "#{res_class_path}/#{one_res_id}"
371
544
  end
372
545
  case command
373
546
  when :list
374
547
  # 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']}
548
+ resp = @api_node.read(res_class_path,options.get_option(:value))
549
+ return {
550
+ type: :object_list,
551
+ data: resp[:data],
552
+ fields: %w[id status start_spec.direction start_spec.remote_user start_spec.remote_host start_spec.destination_path]
553
+ }
378
554
  when :cancel
379
- resp=@api_node.cancel(one_res_path)
555
+ resp = @api_node.cancel(one_res_path)
380
556
  return { type: :other_struct, data: resp[:data] }
381
557
  when :show
382
- resp=@api_node.read(one_res_path)
558
+ resp = @api_node.read(one_res_path)
383
559
  return { type: :other_struct, data: resp[:data] }
384
560
  else
385
561
  raise 'error'
386
562
  end
387
563
  when :access_key
388
- return entity_action(@api_node,'access_keys',id_default: 'self')
564
+ ak_command = options.get_next_command([Plugin::ALL_OPS,:do].flatten)
565
+ case ak_command
566
+ when *Plugin::ALL_OPS then return entity_command(ak_command,@api_node,'access_keys',id_default: 'self')
567
+ when :do
568
+ access_key = options.get_next_argument('access key id')
569
+ ak_info=@api_node.read("access_keys/#{access_key}")[:data]
570
+ # change API if needed
571
+ if !access_key.eql?('self')
572
+ secret=config.vault.get(username: access_key)[:secret] #, url: @api_node.params[:base_url] : TODO: better handle vault
573
+ @api_node.params[:auth][:username]=access_key
574
+ @api_node.params[:auth][:password]=secret
575
+ end
576
+ command_repo = options.get_next_command(NODE4_COMMANDS)
577
+ return execute_node_gen4_command(command_repo,ak_info['root_file_id'])
578
+ end
389
579
  when :service
390
- command=options.get_next_command([:list, :create, :delete])
580
+ command = options.get_next_command(%i[list create delete])
391
581
  if [:delete].include?(command)
392
- svcid=instance_identifier()
582
+ svcid = instance_identifier
393
583
  end
394
584
  case command
395
585
  when :list
396
- resp=@api_node.read('rund/services')
586
+ resp = @api_node.read('rund/services')
397
587
  return { type: :object_list, data: resp[:data]['services'] }
398
588
  when :create
399
589
  # @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)
590
+ params = options.get_next_argument('Run creation data (structure)')
591
+ resp = @api_node.create('rund/services',params)
402
592
  return Main.result_status("#{resp[:data]['id']} created")
403
593
  when :delete
404
594
  @api_node.delete("rund/services/#{svcid}")
405
595
  return Main.result_status("#{svcid} deleted")
406
596
  end
407
597
  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}"
598
+ res_class_path = 'v3/watchfolders'
599
+ command = options.get_next_command(%i[create list show modify delete state])
600
+ if %i[show modify delete state].include?(command)
601
+ one_res_id = instance_identifier
602
+ one_res_path = "#{res_class_path}/#{one_res_id}"
413
603
  end
414
604
  # 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'
605
+ @api_node.params[:headers] ||= {}
606
+ @api_node.params[:headers]['X-aspera-WF-version'] = '2017_10_23'
417
607
  case command
418
608
  when :create
419
- resp=@api_node.create(res_class_path,options.get_option(:value,:mandatory))
609
+ resp = @api_node.create(res_class_path,options.get_option(:value,is_type: :mandatory))
420
610
  return Main.result_status("#{resp[:data]['id']} created")
421
611
  when :list
422
- resp=@api_node.read(res_class_path,options.get_option(:value,:optional))
612
+ resp = @api_node.read(res_class_path,options.get_option(:value))
423
613
  return { type: :value_list, data: resp[:data]['ids'], name: 'id' }
424
614
  when :show
425
615
  return { type: :single_object, data: @api_node.read(one_res_path)[:data]}
426
616
  when :modify
427
- @api_node.update(one_res_path,options.get_option(:value,:mandatory))
617
+ @api_node.update(one_res_path,options.get_option(:value,is_type: :mandatory))
428
618
  return Main.result_status("#{one_res_id} updated")
429
619
  when :delete
430
620
  @api_node.delete(one_res_path)
@@ -433,30 +623,30 @@ fields: ['id','status','start_spec.direction','start_spec.remote_user','start_sp
433
623
  return { type: :single_object, data: @api_node.read("#{one_res_path}/state")[:data] }
434
624
  end
435
625
  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||={}
626
+ command = options.get_next_command(%i[session file])
627
+ validator_id = options.get_option(:validator)
628
+ validation = {'validator_id' => validator_id} unless validator_id.nil?
629
+ request_data = options.get_option(:value)
630
+ request_data ||= {}
441
631
  case command
442
632
  when :session
443
- command=options.get_next_command([:list])
633
+ command = options.get_next_command([:list])
444
634
  case command
445
635
  when :list
446
- request_data.deep_merge!({'validation'=>validation}) unless validation.nil?
447
- resp=@api_node.create('services/rest/transfers/v1/sessions',request_data)
636
+ request_data.deep_merge!({'validation' => validation}) unless validation.nil?
637
+ resp = @api_node.create('services/rest/transfers/v1/sessions',request_data)
448
638
  return { type: :object_list, data: resp[:data]['session_info_result']['session_info'],
449
- fields: ['session_uuid','status','transport','direction','bytes_transferred']}
639
+ fields: %w[session_uuid status transport direction bytes_transferred]}
450
640
  end
451
641
  when :file
452
- command=options.get_next_command([:list, :modify])
642
+ command = options.get_next_command(%i[list modify])
453
643
  case command
454
644
  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)
645
+ request_data.deep_merge!({'validation' => validation}) unless validation.nil?
646
+ resp = @api_node.create('services/rest/transfers/v1/files',request_data)[:data]
647
+ resp = JSON.parse(resp) if resp.is_a?(String)
458
648
  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']}
649
+ return { type: :object_list, data: resp['file_transfer_info_result']['file_transfer_info'], fields: %w[session_uuid file_id status path]}
460
650
  when :modify
461
651
  request_data.deep_merge!(validation) unless validation.nil?
462
652
  @api_node.update('services/rest/transfers/v1/files',request_data)
@@ -464,17 +654,17 @@ fields: ['session_uuid','status','transport','direction','bytes_transferred']}
464
654
  end
465
655
  end
466
656
  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)
657
+ browse_params = {
658
+ 'nodeUser' => options.get_option(:username,is_type: :mandatory),
659
+ 'nodePW' => options.get_option(:password,is_type: :mandatory),
660
+ 'nodeURL' => options.get_option(:url,is_type: :mandatory)
471
661
  }
472
662
  # 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)
663
+ encoded_params = Base64.strict_encode64(Zlib::Deflate.deflate(JSON.generate(browse_params))).gsub(/=+$/, '').tr('+/', '-_').reverse
664
+ OpenApplication.instance.uri(options.get_option(:asperabrowserurl) + '?goto=' + encoded_params)
475
665
  return Main.result_status('done')
476
666
  when :basic_token
477
- return Main.result_status('Basic '+Base64.strict_encode64("#{options.get_option(:username,:mandatory)}:#{options.get_option(:password,:mandatory)}"))
667
+ return Main.result_status(Rest.basic_creds(options.get_option(:username,is_type: :mandatory),options.get_option(:password,is_type: :mandatory)))
478
668
  end # case command
479
669
  raise 'ERROR: shall not reach this line'
480
670
  end # execute_action