aspera-cli 4.5.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 (104) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +1 -0
  3. data/README.md +1894 -1574
  4. data/bin/ascli +21 -1
  5. data/bin/asession +38 -34
  6. data/docs/test_env.conf +14 -3
  7. data/examples/aoc.rb +17 -15
  8. data/examples/dascli +26 -0
  9. data/examples/faspex4.rb +42 -35
  10. data/examples/proxy.pac +1 -1
  11. data/examples/transfer.rb +38 -37
  12. data/lib/aspera/aoc.rb +245 -205
  13. data/lib/aspera/ascmd.rb +111 -90
  14. data/lib/aspera/ats_api.rb +16 -14
  15. data/lib/aspera/cli/basic_auth_plugin.rb +19 -18
  16. data/lib/aspera/cli/extended_value.rb +50 -39
  17. data/lib/aspera/cli/formater.rb +161 -135
  18. data/lib/aspera/cli/info.rb +18 -0
  19. data/lib/aspera/cli/listener/line_dump.rb +4 -2
  20. data/lib/aspera/cli/listener/logger.rb +3 -1
  21. data/lib/aspera/cli/listener/progress.rb +20 -21
  22. data/lib/aspera/cli/listener/progress_multi.rb +29 -31
  23. data/lib/aspera/cli/main.rb +194 -183
  24. data/lib/aspera/cli/manager.rb +213 -206
  25. data/lib/aspera/cli/plugin.rb +71 -49
  26. data/lib/aspera/cli/plugins/alee.rb +8 -7
  27. data/lib/aspera/cli/plugins/aoc.rb +675 -558
  28. data/lib/aspera/cli/plugins/ats.rb +116 -109
  29. data/lib/aspera/cli/plugins/bss.rb +35 -34
  30. data/lib/aspera/cli/plugins/config.rb +722 -542
  31. data/lib/aspera/cli/plugins/console.rb +28 -22
  32. data/lib/aspera/cli/plugins/cos.rb +28 -37
  33. data/lib/aspera/cli/plugins/faspex.rb +281 -227
  34. data/lib/aspera/cli/plugins/faspex5.rb +129 -84
  35. data/lib/aspera/cli/plugins/node.rb +426 -232
  36. data/lib/aspera/cli/plugins/orchestrator.rb +106 -98
  37. data/lib/aspera/cli/plugins/preview.rb +196 -191
  38. data/lib/aspera/cli/plugins/server.rb +131 -126
  39. data/lib/aspera/cli/plugins/shares.rb +49 -36
  40. data/lib/aspera/cli/plugins/sync.rb +27 -28
  41. data/lib/aspera/cli/transfer_agent.rb +84 -79
  42. data/lib/aspera/cli/version.rb +3 -1
  43. data/lib/aspera/colors.rb +37 -28
  44. data/lib/aspera/command_line_builder.rb +84 -63
  45. data/lib/aspera/cos_node.rb +68 -34
  46. data/lib/aspera/data_repository.rb +4 -2
  47. data/lib/aspera/environment.rb +61 -46
  48. data/lib/aspera/fasp/agent_base.rb +36 -31
  49. data/lib/aspera/fasp/agent_connect.rb +44 -37
  50. data/lib/aspera/fasp/agent_direct.rb +101 -104
  51. data/lib/aspera/fasp/agent_httpgw.rb +91 -90
  52. data/lib/aspera/fasp/agent_node.rb +36 -33
  53. data/lib/aspera/fasp/agent_trsdk.rb +28 -31
  54. data/lib/aspera/fasp/error.rb +3 -1
  55. data/lib/aspera/fasp/error_info.rb +81 -54
  56. data/lib/aspera/fasp/installation.rb +171 -151
  57. data/lib/aspera/fasp/listener.rb +2 -0
  58. data/lib/aspera/fasp/parameters.rb +105 -111
  59. data/lib/aspera/fasp/parameters.yaml +305 -249
  60. data/lib/aspera/fasp/resume_policy.rb +20 -20
  61. data/lib/aspera/fasp/transfer_spec.rb +27 -0
  62. data/lib/aspera/fasp/uri.rb +31 -29
  63. data/lib/aspera/faspex_gw.rb +95 -118
  64. data/lib/aspera/hash_ext.rb +12 -13
  65. data/lib/aspera/id_generator.rb +11 -9
  66. data/lib/aspera/keychain/encrypted_hash.rb +73 -57
  67. data/lib/aspera/keychain/macos_security.rb +27 -29
  68. data/lib/aspera/log.rb +40 -39
  69. data/lib/aspera/nagios.rb +24 -22
  70. data/lib/aspera/node.rb +38 -30
  71. data/lib/aspera/oauth.rb +217 -248
  72. data/lib/aspera/open_application.rb +9 -7
  73. data/lib/aspera/persistency_action_once.rb +15 -14
  74. data/lib/aspera/persistency_folder.rb +15 -18
  75. data/lib/aspera/preview/file_types.rb +266 -270
  76. data/lib/aspera/preview/generator.rb +94 -92
  77. data/lib/aspera/preview/image_error.png +0 -0
  78. data/lib/aspera/preview/options.rb +20 -17
  79. data/lib/aspera/preview/utils.rb +99 -102
  80. data/lib/aspera/preview/video_error.png +0 -0
  81. data/lib/aspera/{proxy_auto_config.erb.js → proxy_auto_config.js} +23 -31
  82. data/lib/aspera/proxy_auto_config.rb +114 -21
  83. data/lib/aspera/rest.rb +144 -142
  84. data/lib/aspera/rest_call_error.rb +3 -2
  85. data/lib/aspera/rest_error_analyzer.rb +31 -31
  86. data/lib/aspera/rest_errors_aspera.rb +18 -16
  87. data/lib/aspera/secret_hider.rb +68 -0
  88. data/lib/aspera/ssh.rb +20 -16
  89. data/lib/aspera/sync.rb +57 -54
  90. data/lib/aspera/temp_file_manager.rb +20 -14
  91. data/lib/aspera/timer_limiter.rb +10 -8
  92. data/lib/aspera/uri_reader.rb +14 -15
  93. data/lib/aspera/web_auth.rb +85 -80
  94. data.tar.gz.sig +0 -0
  95. metadata +169 -40
  96. metadata.gz.sig +2 -0
  97. data/bin/dascli +0 -13
  98. data/docs/Makefile +0 -63
  99. data/docs/README.erb.md +0 -4221
  100. data/docs/README.md +0 -13
  101. data/docs/diagrams.txt +0 -49
  102. data/docs/doc_tools.rb +0 -58
  103. data/lib/aspera/cli/plugins/shares2.rb +0 -114
  104. data/lib/aspera/fasp/default.rb +0 -17
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'aspera/cli/basic_auth_plugin'
2
4
  require 'aspera/nagios'
3
5
  require 'aspera/hash_ext'
4
6
  require 'aspera/id_generator'
5
7
  require 'aspera/node'
8
+ require 'aspera/fasp/transfer_spec'
6
9
  require 'base64'
7
10
  require 'zlib'
8
11
 
@@ -12,65 +15,66 @@ module Aspera
12
15
  class Node < BasicAuthPlugin
13
16
  class << self
14
17
  def detect(base_url)
15
- api=Rest.new({:base_url=>base_url})
16
- result=api.call({:operation=>'GET',:subpath=>'ping'})
18
+ api = Rest.new({ base_url: base_url})
19
+ result = api.call({ operation: 'GET', subpath: 'ping'})
17
20
  if result[:http].body.eql?('')
18
- return {:product=>:node,:version=>'unknown'}
21
+ return { product: :node, version: 'unknown'}
19
22
  end
20
23
  return nil
21
24
  end
22
25
  end
23
- 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>'
24
- 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
25
33
 
26
34
  def initialize(env)
27
35
  super(env)
28
- # 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)
29
37
  @add_request_param = env[:add_request_param] || {}
30
- unless env[:skip_basic_auth_options]
31
- self.options.add_opt_simple(:validator,"identifier of validator (optional for central)")
32
- self.options.add_opt_simple(:asperabrowserurl,"URL for simple aspera web ui")
33
- self.options.add_opt_simple(:name,"sync name")
34
- self.options.add_opt_list(:token_type,[:aspera,:basic,:hybrid],'Type of token used for transfers')
35
- self.options.set_option(:asperabrowserurl,'https://asperabrowser.mybluemix.net')
36
- self.options.set_option(:token_type,:aspera)
37
- self.options.parse_options!
38
- end
38
+ options.add_opt_simple(:validator,'identifier of validator (optional for central)')
39
+ options.add_opt_simple(:asperabrowserurl,'URL for simple aspera web ui')
40
+ options.add_opt_simple(:sync_name,'sync name')
41
+ options.add_opt_list(:token_type,%i[aspera basic hybrid],'Type of token used for transfers')
42
+ options.set_option(:asperabrowserurl,'https://asperabrowser.mybluemix.net')
43
+ options.set_option(:token_type,:aspera)
44
+ options.parse_options!
39
45
  return if env[:man_only]
40
- if env.has_key?(:node_api)
41
- @api_node=env[:node_api]
42
- else
43
- if self.options.get_option(:password,:mandatory).start_with?('Bearer ')
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 ')
44
50
  # info is provided like node_info of aoc
45
- @api_node=Rest.new({
46
- base_url: self.options.get_option(:url,:mandatory),
47
- headers: {
48
- 'Authorization' => self.options.get_option(:password,:mandatory),
49
- 'X-Aspera-AccessKey' => self.options.get_option(:username,:mandatory),
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)
50
56
  }
51
57
  })
52
58
  else
53
59
  # this is normal case
54
- @api_node=basic_auth_api
60
+ basic_auth_api
55
61
  end
56
- end
57
62
  end
58
63
 
59
64
  def c_textify_browse(table_data)
60
- 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 }
61
66
  end
62
67
 
63
68
  # key/value is defined in main in hash_table
64
69
  def c_textify_bool_list_result(list,name_list)
65
70
  list.each_index do |i|
66
- if name_list.include?(list[i]['key'])
67
- list[i]['value'].each do |item|
68
- list.push({'key'=>item['name'],'value'=>item['value']})
69
- end
70
- list.delete_at(i)
71
- # continue at same index because we delete current one
72
- redo
71
+ next unless name_list.include?(list[i]['key'])
72
+ list[i]['value'].each do |item|
73
+ list.push({'key' => item['name'],'value' => item['value']})
73
74
  end
75
+ list.delete_at(i)
76
+ # continue at same index because we delete current one
77
+ redo
74
78
  end
75
79
  end
76
80
 
@@ -80,11 +84,11 @@ module Aspera
80
84
  case result[:type]
81
85
  when :object_list
82
86
  result[:data].each do |item|
83
- item[column].replace(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)
84
88
  end
85
89
  when :single_object
86
- item=result[:data]
87
- item[column].replace(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)
88
92
  end
89
93
  end
90
94
  return result
@@ -92,366 +96,556 @@ module Aspera
92
96
 
93
97
  # translates paths results into CLI result, and removes prefix
94
98
  def c_result_translate_rem_prefix(resp,type,success_msg,path_prefix)
95
- resres={:data=>[],:type=>:object_list,:fields=>[type,'result']}
99
+ resres = { data: [], type: :object_list, fields: [type,'result']}
96
100
  JSON.parse(resp[:http].body)['paths'].each do |p|
97
- result=success_msg
101
+ result = success_msg
98
102
  if p.has_key?('error')
99
103
  Log.log.error("#{p['error']['user_message']} : #{p['path']}")
100
- result="ERROR: "+p['error']['user_message']
104
+ result = 'ERROR: ' + p['error']['user_message']
101
105
  end
102
- resres[:data].push({type=>p['path'],'result'=>result})
106
+ resres[:data].push({type => p['path'],'result' => result})
103
107
  end
104
108
  return c_result_remove_prefix_path(resres,type,path_prefix)
105
109
  end
106
110
 
107
111
  # get path arguments from command line, and add prefix
108
112
  def get_next_arg_add_prefix(path_prefix,name,number=:single)
109
- thepath=self.options.get_next_argument(name,number)
113
+ thepath = options.get_next_argument(name,expected: number)
110
114
  return thepath if path_prefix.nil?
111
115
  return File.join(path_prefix,thepath) if thepath.is_a?(String)
112
116
  return thepath.map {|p| File.join(path_prefix,p)} if thepath.is_a?(Array)
113
- raise StandardError,"expect: nil, String or Array"
117
+ raise StandardError,'expect: nil, String or Array'
114
118
  end
115
119
 
116
- 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
117
121
 
118
- COMMON_ACTIONS=[:browse, :upload, :download, :api_details ].concat(SIMPLE_ACTIONS)
122
+ COMMON_ACTIONS = %i[browse upload download api_details].concat(SIMPLE_ACTIONS).freeze
119
123
 
120
124
  # common API to node and Shares
121
125
  # prefix_path is used to list remote sources in Faspex
122
126
  def execute_simple_common(command,prefix_path)
123
127
  case command
124
128
  when :health
125
- nagios=Nagios.new
129
+ nagios = Nagios.new
126
130
  begin
127
- info=@api_node.read('info')[:data]
131
+ info = @api_node.read('info')[:data]
128
132
  nagios.add_ok('node api','accessible')
129
133
  nagios.check_time_offset(info['current_time'],'node api')
130
- nagios.check_product_version( 'node api','entsrv', info['version'])
131
- rescue => e
134
+ nagios.check_product_version('node api','entsrv', info['version'])
135
+ rescue StandardError => e
132
136
  nagios.add_critical('node api',e.to_s)
133
137
  end
134
138
  begin
135
- @api_node.call({:operation=>'POST',:subpath=>'services/soap/Transfer-201210',: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
136
144
  nagios.add_ok('central','accessible by node')
137
- rescue => e
145
+ rescue StandardError => e
138
146
  nagios.add_critical('central',e.to_s)
139
147
  end
140
148
  return nagios.result
141
149
  when :events
142
- events=@api_node.read('events',self.options.get_option(:value,:optional))[:data]
143
- return { :type=>:object_list, :data => events}
150
+ events = @api_node.read('events',options.get_option(:value))[:data]
151
+ return { type: :object_list, data: events}
144
152
  when :info
145
- node_info=@api_node.read('info')[:data]
146
- 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])}}
147
155
  when :license # requires: asnodeadmin -mu <node user> --acl-add=internal --internal
148
- node_license=@api_node.read('license')[:data]
149
- if node_license['failure'].is_a?(String) and node_license['failure'].include?('ACL')
150
- Log.log.error("server must have: asnodeadmin -mu <node user> --acl-add=internal --internal")
156
+ node_license = @api_node.read('license')[:data]
157
+ if node_license['failure'].is_a?(String) && node_license['failure'].include?('ACL')
158
+ Log.log.error('server must have: asnodeadmin -mu <node user> --acl-add=internal --internal')
151
159
  end
152
- return { :type=>:single_object, :data => node_license}
160
+ return { type: :single_object, data: node_license}
153
161
  when :delete
154
- paths_to_delete = get_next_arg_add_prefix(prefix_path,"file list",:multiple)
155
- resp=@api_node.create('files/delete',{:paths=>paths_to_delete.map{|i| {'path'=>i.start_with?('/') ? i : '/'+i} }})
162
+ paths_to_delete = get_next_arg_add_prefix(prefix_path,'file list',:multiple)
163
+ resp = @api_node.create('files/delete',{ paths: paths_to_delete.map{|i| {'path' => i.start_with?('/') ? i : '/' + i} }})
156
164
  return c_result_translate_rem_prefix(resp,'file','deleted',prefix_path)
157
165
  when :search
158
- search_root = get_next_arg_add_prefix(prefix_path,"search root")
159
- parameters={'path'=>search_root}
160
- other_options=self.options.get_option(:value,:optional)
166
+ search_root = get_next_arg_add_prefix(prefix_path,'search root')
167
+ parameters = {'path' => search_root}
168
+ other_options = options.get_option(:value)
161
169
  parameters.merge!(other_options) unless other_options.nil?
162
- resp=@api_node.create('files/search',parameters)
163
- 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']}
164
172
  return Main.result_empty if result[:data].empty?
165
- result[:fields]=result[:data].first.keys.select{|i|!['basename','permissions'].include?(i)}
173
+ result[:fields] = result[:data].first.keys.reject{|i|SEARCH_REMOVE_FIELDS.include?(i)}
166
174
  self.format.display_status("Items: #{resp[:data]['item_count']}/#{resp[:data]['total_count']}")
167
175
  self.format.display_status("params: #{resp[:data]['parameters'].keys.map{|k|"#{k}:#{resp[:data]['parameters'][k]}"}.join(',')}")
168
176
  return c_result_remove_prefix_path(result,'path',prefix_path)
169
177
  when :space
170
178
  # TODO: could be a list of path
171
- path_list=get_next_arg_add_prefix(prefix_path,"folder path or ext.val. list")
172
- path_list=[path_list] unless path_list.is_a?(Array)
173
- resp=@api_node.create('space',{ "paths" => path_list.map {|i| {:path=>i} } } )
174
- 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}
175
183
  #return c_result_translate_rem_prefix(resp,'folder','created',prefix_path)
176
184
  return c_result_remove_prefix_path(result,'path',prefix_path)
177
185
  when :mkdir
178
- path_list=get_next_arg_add_prefix(prefix_path,"folder path or ext.val. list")
179
- 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)
180
188
  #TODO: a command for that ?
181
- #resp=@api_node.create('space',{ "paths" => path_list.map {|i| {:type=>:directory,:path=>i} } } )
182
- resp=@api_node.create('files/create',{ "paths" => [{ :type => :directory, :path => path_list } ] } )
189
+ #resp=@api_node.create('space',{ "paths" => path_list.map {|i| { type: :directory, path: i} } } )
190
+ resp = @api_node.create('files/create',{ 'paths' => [{ type: :directory, path: path_list }] })
183
191
  return c_result_translate_rem_prefix(resp,'folder','created',prefix_path)
184
192
  when :mklink
185
- target=get_next_arg_add_prefix(prefix_path,"target")
186
- path_list=get_next_arg_add_prefix(prefix_path,"link path")
187
- 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} }] })
188
196
  return c_result_translate_rem_prefix(resp,'folder','created',prefix_path)
189
197
  when :mkfile
190
- path_list=get_next_arg_add_prefix(prefix_path,"file path")
191
- contents64=Base64.strict_encode64(self.options.get_next_argument("contents"))
192
- 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 }] })
193
201
  return c_result_translate_rem_prefix(resp,'folder','created',prefix_path)
194
202
  when :rename
195
- path_base=get_next_arg_add_prefix(prefix_path,"path_base")
196
- path_src=get_next_arg_add_prefix(prefix_path,"path_src")
197
- path_dst=get_next_arg_add_prefix(prefix_path,"path_dst")
198
- 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 }] })
199
207
  return c_result_translate_rem_prefix(resp,'entry','moved',prefix_path)
200
208
  when :browse
201
- thepath=get_next_arg_add_prefix(prefix_path,"path")
202
- query={ :path => thepath}
203
- additional_query=self.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)
204
212
  query.merge!(additional_query) unless additional_query.nil?
205
- send_result=@api_node.create('files/browse', query)[:data]
213
+ send_result = @api_node.create('files/browse', query)[:data]
206
214
  #example: send_result={'items'=>[{'file'=>"filename1","permissions"=>[{'name'=>'read'},{'name'=>'write'}]}]}
207
215
  # if there is no items
208
216
  case send_result['self']['type']
209
217
  when 'directory','container' # directory: node, container: shares
210
- 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) } }
211
219
  self.format.display_status("Items: #{send_result['item_count']}/#{send_result['total_count']}")
212
220
  else # 'file','symbolic_link'
213
- result={ :data => send_result['self'] , :type => :single_object}
214
- #result={ :data => [send_result['self']] , :type => :object_list, :textify => lambda { |table_data| c_textify_browse(table_data) } }
221
+ result = { data: send_result['self'], type: :single_object}
222
+ #result={ data: [send_result['self']] , type: :object_list, textify: lambda { |table_data| c_textify_browse(table_data) } }
215
223
  #raise "unknown type: #{send_result['self']['type']}"
216
224
  end
217
225
  return c_result_remove_prefix_path(result,'path',prefix_path)
218
226
  when :upload,:download
219
- token_type=self.options.get_option(:token_type,:optional)
227
+ token_type = options.get_option(:token_type)
220
228
  # nil if Shares 1.x
221
- token_type=:aspera if token_type.nil?
229
+ token_type = :aspera if token_type.nil?
222
230
  case token_type
223
231
  when :aspera,:hybrid
224
- transfer_paths=case command
225
- when :upload;[ { :destination => self.transfer.destination_folder('send') } ]
226
- when :download;self.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
- raise "shall have auth" unless @api_node.params[:auth].is_a?(Hash)
236
- raise "shall be basic auth" unless @api_node.params[:auth][:type].eql?(:basic)
237
- transfer_spec={
238
- 'remote_host'=>URI.parse(@api_node.params[:base_url]).host,
239
- 'remote_user'=>Aspera::Fasp::Default::ACCESS_KEY_TRANSFER_USER,
240
- 'ssh_port' =>Aspera::Fasp::Default::SSH_PORT,
241
- 'direction' =>case command;when :upload;'send';when :download;'recv';else raise "Error";end
242
- }
245
+ raise 'shall have auth' unless @api_node.params[:auth].is_a?(Hash)
246
+ raise 'shall be basic auth' unless @api_node.params[:auth][:type].eql?(:basic)
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)
259
+ }.deep_merge(@add_request_param)
243
260
  else raise "ERROR: token_type #{tt}"
244
261
  end
245
- if [:basic,:hybrid].include?(token_type)
262
+ if %i[basic hybrid].include?(token_type)
246
263
  Aspera::Node.set_ak_basic_token(transfer_spec,@api_node.params[:auth][:username],@api_node.params[:auth][:password])
247
264
  end
248
- return Main.result_transfer(self.transfer.start(transfer_spec,{:src=>:node_gen3}))
265
+ return Main.result_transfer(transfer.start(transfer_spec,{ src: :node_gen3}))
249
266
  when :api_details
250
- return { :type=>:single_object, :data => @api_node.params }
267
+ return { type: :single_object, data: @api_node.params }
251
268
  end
252
269
  end
253
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
+
254
429
  def execute_async
255
- command=self.options.get_next_command([:list,:delete,:files,:show,:counters,:bandwidth])
430
+ command = options.get_next_command(%i[list delete files show counters bandwidth])
256
431
  unless command.eql?(:list)
257
- asyncname=self.options.get_option(:name,:optional)
432
+ asyncname = options.get_option(:sync_name)
258
433
  if asyncname.nil?
259
- asyncid=self.instance_identifier()
260
- if asyncid.eql?('ALL') and [:show,:delete].include?(command)
261
- 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']
262
437
  else
263
438
  Integer(asyncid) # must be integer
264
- asyncids=[asyncid]
439
+ asyncids = [asyncid]
265
440
  end
266
441
  else
267
- asyncids=@api_node.read('async/list')[:data]['sync_ids']
268
- summaries=@api_node.create('async/summary',{'syncs' => asyncids})[:data]['sync_summaries']
269
- 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)}
270
445
  raise "no such sync: #{asyncname}" if selected.nil?
271
- asyncid=selected['snid']
272
- asyncids=[asyncid]
446
+ asyncid = selected['snid']
447
+ asyncids = [asyncid]
273
448
  end
274
- pdata={'syncs' => asyncids}
449
+ pdata = {'syncs' => asyncids}
275
450
  end
276
451
  case command
277
452
  when :list
278
- resp=@api_node.read('async/list')[:data]['sync_ids']
279
- return { :type => :value_list, :data => resp, :name=>'id' }
453
+ resp = @api_node.read('async/list')[:data]['sync_ids']
454
+ return { type: :value_list, data: resp, name: 'id' }
280
455
  when :show
281
- resp=@api_node.create('async/summary',pdata)[:data]['sync_summaries']
456
+ resp = @api_node.create('async/summary',pdata)[:data]['sync_summaries']
282
457
  return Main.result_empty if resp.empty?
283
- if asyncid.eql?('ALL')
284
- return { :type => :object_list, :data => resp, :fields => ['snid','name','local_dir','remote_dir'] }
285
- else
286
- return { :type => :single_object, :data => resp.first }
287
- end
458
+ return { type: :object_list, data: resp, fields: %w[snid name local_dir remote_dir] } if asyncid.eql?('ALL')
459
+ return { type: :single_object, data: resp.first }
288
460
  when :delete
289
- resp=@api_node.create('async/delete',pdata)[:data]
290
- return { :type => :single_object, :data => resp, :name=>'id' }
461
+ resp = @api_node.create('async/delete',pdata)[:data]
462
+ return { type: :single_object, data: resp, name: 'id' }
291
463
  when :bandwidth
292
- pdata['seconds']=100 # TODO: as parameter with --value
293
- resp=@api_node.create('async/bandwidth',pdata)[:data]
294
- 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']
295
467
  return Main.result_empty if data.empty?
296
- data=data.first[asyncid]['data']
297
- return { :type => :object_list, :data => data, :name=>'id' }
468
+ data = data.first[asyncid]['data']
469
+ return { type: :object_list, data: data, name: 'id' }
298
470
  when :files
299
471
  # count int
300
472
  # filename str
301
473
  # skip int
302
474
  # status int
303
- filter=self.options.get_option(:value,:optional)
475
+ filter = options.get_option(:value)
304
476
  pdata.merge!(filter) unless filter.nil?
305
- resp=@api_node.create('async/files',pdata)[:data]
306
- data=resp['sync_files']
307
- data=data.first[asyncid] unless data.empty?
308
- iteration_data=[]
309
- skip_ids_persistency=nil
310
- if self.options.get_option(:once_only,:mandatory)
311
- skip_ids_persistency=PersistencyActionOnce.new(
312
- manager: @agents[:persistency],
313
- data: iteration_data,
314
- id: IdGenerator.from_list(['sync_files',self.options.get_option(:url,:mandatory),self.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]))
315
491
  unless iteration_data.first.nil?
316
- data.select!{|l| l['fnid'].to_i>iteration_data.first}
492
+ data.select!{|l| l['fnid'].to_i > iteration_data.first}
317
493
  end
318
- iteration_data[0]=data.last['fnid'].to_i unless data.empty?
494
+ iteration_data[0] = data.last['fnid'].to_i unless data.empty?
319
495
  end
320
496
  return Main.result_empty if data.empty?
321
- skip_ids_persistency.save unless skip_ids_persistency.nil?
322
- return { :type => :object_list, :data => data, :name=>'id' }
497
+ skip_ids_persistency&.save
498
+ return { type: :object_list, data: data, name: 'id' }
323
499
  when :counters
324
- 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
325
501
  return Main.result_empty if resp.nil?
326
- return { :type => :single_object, :data => resp }
502
+ return { type: :single_object, data: resp }
327
503
  end
328
504
  end
329
505
 
330
- 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
331
507
 
332
508
  def execute_action(command=nil,prefix_path=nil)
333
- command||=self.options.get_next_command(ACTIONS)
509
+ command ||= options.get_next_command(ACTIONS)
334
510
  case command
335
- when *COMMON_ACTIONS; return execute_simple_common(command,prefix_path)
336
- when :async; return execute_async()
511
+ when *COMMON_ACTIONS then return execute_simple_common(command,prefix_path)
512
+ when :async then return execute_async
337
513
  when :stream
338
- command=self.options.get_next_command([ :list, :create, :show, :modify, :cancel ])
514
+ command = options.get_next_command(%i[list create show modify cancel])
339
515
  case command
340
516
  when :list
341
- resp=@api_node.read('ops/transfers',self.options.get_option(:value,:optional))
342
- 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?
343
519
  when :create
344
- resp=@api_node.create('streams',self.options.get_option(:value,:mandatory))
345
- return { :type => :single_object, :data => resp[:data] }
520
+ resp = @api_node.create('streams',options.get_option(:value,is_type: :mandatory))
521
+ return { type: :single_object, data: resp[:data] }
346
522
  when :show
347
- trid=self.options.get_next_argument("transfer id")
348
- resp=@api_node.read('ops/transfers/'+trid)
349
- return { :type=>:other_struct, :data => resp[:data] }
523
+ trid = options.get_next_argument('transfer id')
524
+ resp = @api_node.read('ops/transfers/' + trid)
525
+ return { type: :other_struct, data: resp[:data] }
350
526
  when :modify
351
- trid=self.options.get_next_argument("transfer id")
352
- resp=@api_node.update('streams/'+trid,self.options.get_option(:value,:mandatory))
353
- return { :type=>:other_struct, :data => resp[:data] }
527
+ trid = options.get_next_argument('transfer id')
528
+ resp = @api_node.update('streams/' + trid,options.get_option(:value,is_type: :mandatory))
529
+ return { type: :other_struct, data: resp[:data] }
354
530
  when :cancel
355
- trid=self.options.get_next_argument("transfer id")
356
- resp=@api_node.cancel('streams/'+trid)
357
- return { :type=>:other_struct, :data => resp[:data] }
531
+ trid = options.get_next_argument('transfer id')
532
+ resp = @api_node.cancel('streams/' + trid)
533
+ return { type: :other_struct, data: resp[:data] }
358
534
  else
359
- raise "error"
535
+ raise 'error'
360
536
  end
361
537
  when :transfer
362
- command=self.options.get_next_command([ :list, :cancel, :show ])
363
- res_class_path='ops/transfers'
364
- if [:cancel, :show].include?(command)
365
- one_res_id=self.instance_identifier()
366
- 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}"
367
543
  end
368
544
  case command
369
545
  when :list
370
- # could use ? :subpath=>'transfers'
371
- resp=@api_node.read(res_class_path,self.options.get_option(:value,:optional))
372
- return { :type => :object_list, :data => resp[:data], :fields=>['id','status','start_spec.direction','start_spec.remote_user','start_spec.remote_host','start_spec.destination_path']}
546
+ # could use ? subpath: 'transfers'
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
+ }
373
553
  when :cancel
374
- resp=@api_node.cancel(one_res_path)
375
- return { :type=>:other_struct, :data => resp[:data] }
554
+ resp = @api_node.cancel(one_res_path)
555
+ return { type: :other_struct, data: resp[:data] }
376
556
  when :show
377
- resp=@api_node.read(one_res_path)
378
- return { :type=>:other_struct, :data => resp[:data] }
557
+ resp = @api_node.read(one_res_path)
558
+ return { type: :other_struct, data: resp[:data] }
379
559
  else
380
- raise "error"
560
+ raise 'error'
381
561
  end
382
562
  when :access_key
383
- return self.entity_action(@api_node,'access_keys',nil,:id,'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
384
578
  when :service
385
- command=self.options.get_next_command([ :list, :create, :delete])
579
+ command = options.get_next_command(%i[list create delete])
386
580
  if [:delete].include?(command)
387
- svcid=self.instance_identifier()
581
+ svcid = instance_identifier
388
582
  end
389
583
  case command
390
584
  when :list
391
- resp=@api_node.read('rund/services')
392
- return { :type=>:object_list, :data => resp[:data]["services"] }
585
+ resp = @api_node.read('rund/services')
586
+ return { type: :object_list, data: resp[:data]['services'] }
393
587
  when :create
394
588
  # @json:'{"type":"WATCHFOLDERD","run_as":{"user":"user1"}}'
395
- params=self.options.get_next_argument("Run creation data (structure)")
396
- 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)
397
591
  return Main.result_status("#{resp[:data]['id']} created")
398
592
  when :delete
399
- resp=@api_node.delete("rund/services/#{svcid}")
593
+ @api_node.delete("rund/services/#{svcid}")
400
594
  return Main.result_status("#{svcid} deleted")
401
595
  end
402
596
  when :watch_folder
403
- res_class_path='v3/watchfolders'
404
- #return entity_action(@api_node,'v3/watchfolders',nil,:id)
405
- command=self.options.get_next_command([ :create, :list, :show, :modify, :delete, :state])
406
- if [:show,:modify,:delete,:state].include?(command)
407
- one_res_id=self.instance_identifier()
408
- 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}"
409
602
  end
410
603
  # hum, to avoid: Unable to convert 2016_09_14 configuration
411
- @api_node.params[:headers]||={}
412
- @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'
413
606
  case command
414
607
  when :create
415
- resp=@api_node.create(res_class_path,self.options.get_option(:value,:mandatory))
608
+ resp = @api_node.create(res_class_path,options.get_option(:value,is_type: :mandatory))
416
609
  return Main.result_status("#{resp[:data]['id']} created")
417
610
  when :list
418
- resp=@api_node.read(res_class_path,self.options.get_option(:value,:optional))
419
- return { :type=>:value_list, :data => resp[:data]['ids'], :name=>'id' }
611
+ resp = @api_node.read(res_class_path,options.get_option(:value))
612
+ return { type: :value_list, data: resp[:data]['ids'], name: 'id' }
420
613
  when :show
421
- return {:type=>:single_object, :data=>@api_node.read(one_res_path)[:data]}
614
+ return { type: :single_object, data: @api_node.read(one_res_path)[:data]}
422
615
  when :modify
423
- @api_node.update(one_res_path,self.options.get_option(:value,:mandatory))
616
+ @api_node.update(one_res_path,options.get_option(:value,is_type: :mandatory))
424
617
  return Main.result_status("#{one_res_id} updated")
425
618
  when :delete
426
619
  @api_node.delete(one_res_path)
427
620
  return Main.result_status("#{one_res_id} deleted")
428
621
  when :state
429
- return { :type=>:single_object, :data => @api_node.read("#{one_res_path}/state")[:data] }
622
+ return { type: :single_object, data: @api_node.read("#{one_res_path}/state")[:data] }
430
623
  end
431
624
  when :central
432
- command=self.options.get_next_command([ :session,:file])
433
- validator_id=self.options.get_option(:validator)
434
- validation={"validator_id"=>validator_id} unless validator_id.nil?
435
- request_data=self.options.get_option(:value,:optional)
436
- 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 ||= {}
437
630
  case command
438
631
  when :session
439
- command=self.options.get_next_command([ :list])
632
+ command = options.get_next_command([:list])
440
633
  case command
441
634
  when :list
442
- request_data.deep_merge!({"validation"=>validation}) unless validation.nil?
443
- resp=@api_node.create('services/rest/transfers/v1/sessions',request_data)
444
- return {:type=>:object_list,:data=>resp[:data]["session_info_result"]["session_info"],:fields=>["session_uuid","status","transport","direction","bytes_transferred"]}
635
+ request_data.deep_merge!({'validation' => validation}) unless validation.nil?
636
+ resp = @api_node.create('services/rest/transfers/v1/sessions',request_data)
637
+ return { type: :object_list, data: resp[:data]['session_info_result']['session_info'],
638
+ fields: %w[session_uuid status transport direction bytes_transferred]}
445
639
  end
446
640
  when :file
447
- command=self.options.get_next_command([ :list, :modify])
641
+ command = options.get_next_command(%i[list modify])
448
642
  case command
449
643
  when :list
450
- request_data.deep_merge!({'validation'=>validation}) unless validation.nil?
451
- resp=@api_node.create('services/rest/transfers/v1/files',request_data)[:data]
452
- 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)
453
647
  Log.dump(:resp,resp)
454
- 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]}
455
649
  when :modify
456
650
  request_data.deep_merge!(validation) unless validation.nil?
457
651
  @api_node.update('services/rest/transfers/v1/files',request_data)
@@ -459,19 +653,19 @@ module Aspera
459
653
  end
460
654
  end
461
655
  when :asperabrowser
462
- browse_params={
463
- 'nodeUser' => self.options.get_option(:username,:mandatory),
464
- 'nodePW' => self.options.get_option(:password,:mandatory),
465
- 'nodeURL' => self.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)
466
660
  }
467
661
  # encode parameters so that it looks good in url
468
- encoded_params=Base64.strict_encode64(Zlib::Deflate.deflate(JSON.generate(browse_params))).gsub(/=+$/, '').tr('+/', '-_').reverse
469
- OpenApplication.instance.uri(self.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)
470
664
  return Main.result_status('done')
471
665
  when :basic_token
472
- return Main.result_status("Basic "+Base64.strict_encode64("#{self.options.get_option(:username,:mandatory)}:#{self.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)))
473
667
  end # case command
474
- raise "ERROR: shall not reach this line"
668
+ raise 'ERROR: shall not reach this line'
475
669
  end # execute_action
476
670
  end # Main
477
671
  end # Plugin