aspera-cli 4.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +3592 -0
- data/bin/ascli +7 -0
- data/bin/asession +89 -0
- data/docs/Makefile +59 -0
- data/docs/README.erb.md +3012 -0
- data/docs/README.md +13 -0
- data/docs/diagrams.txt +49 -0
- data/docs/secrets.make +38 -0
- data/docs/test_env.conf +117 -0
- data/docs/transfer_spec.html +99 -0
- data/examples/aoc.rb +17 -0
- data/examples/proxy.pac +60 -0
- data/examples/transfer.rb +115 -0
- data/lib/aspera/api_detector.rb +60 -0
- data/lib/aspera/ascmd.rb +151 -0
- data/lib/aspera/ats_api.rb +43 -0
- data/lib/aspera/cli/basic_auth_plugin.rb +38 -0
- data/lib/aspera/cli/extended_value.rb +88 -0
- data/lib/aspera/cli/formater.rb +238 -0
- data/lib/aspera/cli/listener/line_dump.rb +17 -0
- data/lib/aspera/cli/listener/logger.rb +20 -0
- data/lib/aspera/cli/listener/progress.rb +52 -0
- data/lib/aspera/cli/listener/progress_multi.rb +91 -0
- data/lib/aspera/cli/main.rb +304 -0
- data/lib/aspera/cli/manager.rb +440 -0
- data/lib/aspera/cli/plugin.rb +90 -0
- data/lib/aspera/cli/plugins/alee.rb +24 -0
- data/lib/aspera/cli/plugins/ats.rb +231 -0
- data/lib/aspera/cli/plugins/bss.rb +71 -0
- data/lib/aspera/cli/plugins/config.rb +806 -0
- data/lib/aspera/cli/plugins/console.rb +62 -0
- data/lib/aspera/cli/plugins/cos.rb +106 -0
- data/lib/aspera/cli/plugins/faspex.rb +377 -0
- data/lib/aspera/cli/plugins/faspex5.rb +93 -0
- data/lib/aspera/cli/plugins/node.rb +438 -0
- data/lib/aspera/cli/plugins/oncloud.rb +937 -0
- data/lib/aspera/cli/plugins/orchestrator.rb +169 -0
- data/lib/aspera/cli/plugins/preview.rb +464 -0
- data/lib/aspera/cli/plugins/server.rb +216 -0
- data/lib/aspera/cli/plugins/shares.rb +63 -0
- data/lib/aspera/cli/plugins/shares2.rb +114 -0
- data/lib/aspera/cli/plugins/sync.rb +65 -0
- data/lib/aspera/cli/plugins/xnode.rb +115 -0
- data/lib/aspera/cli/transfer_agent.rb +251 -0
- data/lib/aspera/cli/version.rb +5 -0
- data/lib/aspera/colors.rb +39 -0
- data/lib/aspera/command_line_builder.rb +137 -0
- data/lib/aspera/fasp/aoc.rb +24 -0
- data/lib/aspera/fasp/connect.rb +99 -0
- data/lib/aspera/fasp/error.rb +21 -0
- data/lib/aspera/fasp/error_info.rb +60 -0
- data/lib/aspera/fasp/http_gw.rb +81 -0
- data/lib/aspera/fasp/installation.rb +240 -0
- data/lib/aspera/fasp/listener.rb +11 -0
- data/lib/aspera/fasp/local.rb +377 -0
- data/lib/aspera/fasp/manager.rb +69 -0
- data/lib/aspera/fasp/node.rb +88 -0
- data/lib/aspera/fasp/parameters.rb +235 -0
- data/lib/aspera/fasp/resume_policy.rb +76 -0
- data/lib/aspera/fasp/uri.rb +51 -0
- data/lib/aspera/faspex_gw.rb +196 -0
- data/lib/aspera/hash_ext.rb +28 -0
- data/lib/aspera/log.rb +80 -0
- data/lib/aspera/nagios.rb +71 -0
- data/lib/aspera/node.rb +14 -0
- data/lib/aspera/oauth.rb +319 -0
- data/lib/aspera/on_cloud.rb +421 -0
- data/lib/aspera/open_application.rb +72 -0
- data/lib/aspera/persistency_action_once.rb +42 -0
- data/lib/aspera/persistency_folder.rb +91 -0
- data/lib/aspera/preview/file_types.rb +300 -0
- data/lib/aspera/preview/generator.rb +258 -0
- data/lib/aspera/preview/image_error.png +0 -0
- data/lib/aspera/preview/options.rb +35 -0
- data/lib/aspera/preview/utils.rb +131 -0
- data/lib/aspera/preview/video_error.png +0 -0
- data/lib/aspera/proxy_auto_config.erb.js +287 -0
- data/lib/aspera/proxy_auto_config.rb +34 -0
- data/lib/aspera/rest.rb +296 -0
- data/lib/aspera/rest_call_error.rb +13 -0
- data/lib/aspera/rest_error_analyzer.rb +98 -0
- data/lib/aspera/rest_errors_aspera.rb +58 -0
- data/lib/aspera/ssh.rb +53 -0
- data/lib/aspera/sync.rb +82 -0
- data/lib/aspera/temp_file_manager.rb +37 -0
- data/lib/aspera/uri_reader.rb +25 -0
- metadata +288 -0
@@ -0,0 +1,937 @@
|
|
1
|
+
require 'aspera/cli/plugins/node'
|
2
|
+
require 'aspera/cli/plugins/ats'
|
3
|
+
require 'aspera/cli/basic_auth_plugin'
|
4
|
+
require 'aspera/cli/transfer_agent'
|
5
|
+
require 'aspera/on_cloud'
|
6
|
+
require 'aspera/persistency_action_once'
|
7
|
+
require 'securerandom'
|
8
|
+
require 'resolv'
|
9
|
+
require 'date'
|
10
|
+
|
11
|
+
module Aspera
|
12
|
+
module Cli
|
13
|
+
module Plugins
|
14
|
+
class Oncloud < BasicAuthPlugin
|
15
|
+
VAL_ALL='ALL'
|
16
|
+
private_constant :VAL_ALL
|
17
|
+
attr_reader :api_aoc
|
18
|
+
def initialize(env)
|
19
|
+
super(env)
|
20
|
+
@default_workspace_id=nil
|
21
|
+
@workspace_name=nil
|
22
|
+
@workspace_id=nil
|
23
|
+
@persist_ids=nil
|
24
|
+
@home_node_file=nil
|
25
|
+
@api_aoc=nil
|
26
|
+
@url_token_data=nil
|
27
|
+
@user_info=nil
|
28
|
+
@ats=Ats.new(@agents)
|
29
|
+
self.options.add_opt_list(:auth,Oauth.auth_types,"type of Oauth authentication")
|
30
|
+
self.options.add_opt_list(:operation,[:push,:pull],"client operation for transfers")
|
31
|
+
self.options.add_opt_simple(:client_id,"API client identifier in application")
|
32
|
+
self.options.add_opt_simple(:client_secret,"API client passcode")
|
33
|
+
self.options.add_opt_simple(:redirect_uri,"API client redirect URI")
|
34
|
+
self.options.add_opt_simple(:private_key,"RSA private key PEM value for JWT (prefix file path with @val:@file:)")
|
35
|
+
self.options.add_opt_simple(:workspace,"name of workspace")
|
36
|
+
self.options.add_opt_simple(:eid,"identifier") # used ?
|
37
|
+
self.options.add_opt_simple(:name,"resource name")
|
38
|
+
self.options.add_opt_simple(:link,"public link to shared resource")
|
39
|
+
self.options.add_opt_simple(:new_user_option,"new user creation option")
|
40
|
+
self.options.add_opt_simple(:from_folder,"share to share source folder")
|
41
|
+
self.options.add_opt_simple(:scope,"scope for AoC API calls")
|
42
|
+
self.options.add_opt_simple(:notify,"notify users that file was received")
|
43
|
+
self.options.add_opt_boolean(:bulk,"bulk operation")
|
44
|
+
self.options.add_opt_boolean(:default_ports,"use standard FASP ports or get from node api")
|
45
|
+
self.options.set_option(:bulk,:no)
|
46
|
+
self.options.set_option(:default_ports,:yes)
|
47
|
+
self.options.set_option(:new_user_option,{'package_contact'=>true})
|
48
|
+
self.options.set_option(:operation,:push)
|
49
|
+
self.options.set_option(:auth,:jwt)
|
50
|
+
self.options.set_option(:scope,OnCloud::SCOPE_FILES_USER)
|
51
|
+
self.options.set_option(:private_key,'@file:'+env[:private_key_path]) if env[:private_key_path].is_a?(String)
|
52
|
+
self.options.parse_options!
|
53
|
+
OnCloud.set_use_default_ports(self.options.get_option(:default_ports))
|
54
|
+
return if env[:man_only]
|
55
|
+
update_aoc_api
|
56
|
+
end
|
57
|
+
|
58
|
+
# call this to populate single AK secret in AoC API object, from options
|
59
|
+
# make sure secret is available
|
60
|
+
def find_ak_secret(ak,mandatory=true)
|
61
|
+
# secret hash is already provisioned
|
62
|
+
# optionally override with specific secret
|
63
|
+
@api_aoc.add_secrets({ak=>self.config.get_secret(ak,mandatory)})
|
64
|
+
# check that secret was provided as single value or dictionary
|
65
|
+
raise CliBadArgument,"Please provide option secret or entry in option secrets for: #{ak}" unless @api_aoc.has_secret(ak) or !mandatory
|
66
|
+
end
|
67
|
+
|
68
|
+
def user_info
|
69
|
+
if @user_info.nil?
|
70
|
+
# get our user's default information
|
71
|
+
# self?embed[]=default_workspace&embed[]=organization
|
72
|
+
@user_info=@api_aoc.read('self')[:data] rescue {
|
73
|
+
'name' => 'unknown',
|
74
|
+
'email' => 'unknown',
|
75
|
+
}
|
76
|
+
end
|
77
|
+
return @user_info
|
78
|
+
end
|
79
|
+
|
80
|
+
# starts transfer using transfer agent
|
81
|
+
def transfer_start(app,direction,node_file,ts_add)
|
82
|
+
ts_add.deep_merge!(OnCloud.analytics_ts(app,direction,@workspace_id,@workspace_name))
|
83
|
+
ts_add.deep_merge!(OnCloud.console_ts(app,user_info['name'],user_info['email']))
|
84
|
+
return self.transfer.start(*@api_aoc.tr_spec(app,direction,node_file,ts_add))
|
85
|
+
end
|
86
|
+
|
87
|
+
NODE4_COMMANDS=[ :browse, :find, :mkdir, :rename, :delete, :upload, :download, :transfer, :http_node_download, :v3, :file, :bearer_token_node, :permissions ]
|
88
|
+
|
89
|
+
def node_gen4_execute_action(top_node_file)
|
90
|
+
command_repo=self.options.get_next_command(NODE4_COMMANDS)
|
91
|
+
return execute_node_gen4_command(command_repo,top_node_file)
|
92
|
+
end
|
93
|
+
|
94
|
+
def execute_node_gen4_command(command_repo,top_node_file)
|
95
|
+
case command_repo
|
96
|
+
when :bearer_token_node
|
97
|
+
thepath=self.options.get_next_argument('path')
|
98
|
+
node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
|
99
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
|
100
|
+
return Main.result_status(node_api.oauth_token)
|
101
|
+
when :browse
|
102
|
+
thepath=self.options.get_next_argument('path')
|
103
|
+
node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
|
104
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
|
105
|
+
file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
|
106
|
+
if file_info['type'].eql?('folder')
|
107
|
+
result=node_api.read("files/#{node_file[:file_id]}/files",self.options.get_option(:value,:optional))
|
108
|
+
items=result[:data]
|
109
|
+
self.format.display_status("Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}")
|
110
|
+
else
|
111
|
+
items=[file_info]
|
112
|
+
end
|
113
|
+
return {:type=>:object_list,:data=>items,:fields=>['name','type','recursive_size','size','modified_time','access_level']}
|
114
|
+
when :find
|
115
|
+
thepath=self.options.get_next_argument('path')
|
116
|
+
exec_prefix='exec:'
|
117
|
+
expression=self.options.get_option(:value,:optional)||"#{exec_prefix}true"
|
118
|
+
node_file=@api_aoc.resolve_node_file(top_node_file,thepath)
|
119
|
+
if expression.start_with?(exec_prefix)
|
120
|
+
test_block=eval "lambda{|f|#{expression[exec_prefix.length..-1]}}"
|
121
|
+
else
|
122
|
+
test_block=lambda{|f|f['name'].match(/#{expression}/)}
|
123
|
+
end
|
124
|
+
return {:type=>:object_list,:data=>@api_aoc.find_files(node_file,test_block),:fields=>['path']}
|
125
|
+
when :mkdir
|
126
|
+
thepath=self.options.get_next_argument('path')
|
127
|
+
containing_folder_path = thepath.split(OnCloud::PATH_SEPARATOR)
|
128
|
+
new_folder=containing_folder_path.pop
|
129
|
+
node_file = @api_aoc.resolve_node_file(top_node_file,containing_folder_path.join(OnCloud::PATH_SEPARATOR))
|
130
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
|
131
|
+
result=node_api.create("files/#{node_file[:file_id]}/files",{:name=>new_folder,:type=>:folder})[:data]
|
132
|
+
return Main.result_status("created: #{result['name']} (id=#{result['id']})")
|
133
|
+
when :rename
|
134
|
+
thepath=self.options.get_next_argument('source path')
|
135
|
+
newname=self.options.get_next_argument('new name')
|
136
|
+
node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
|
137
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
|
138
|
+
result=node_api.update("files/#{node_file[:file_id]}",{:name=>newname})[:data]
|
139
|
+
return Main.result_status("renamed #{thepath} to #{newname}")
|
140
|
+
when :delete
|
141
|
+
thepath=self.options.get_next_argument('path')
|
142
|
+
return do_bulk_operation(thepath,'deleted','path') do |thepath|
|
143
|
+
raise "expecting String (path), got #{thepath.class.name} (#{thepath})" unless thepath.is_a?(String)
|
144
|
+
node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
|
145
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
|
146
|
+
result=node_api.delete("files/#{node_file[:file_id]}")[:data]
|
147
|
+
{'path'=>thepath}
|
148
|
+
end
|
149
|
+
when :transfer
|
150
|
+
# client side is agent
|
151
|
+
# server side is protocol server
|
152
|
+
# in same workspace
|
153
|
+
server_home_node_file=client_home_node_file=top_node_file
|
154
|
+
# default is push
|
155
|
+
case self.options.get_option(:operation,:mandatory)
|
156
|
+
when :push
|
157
|
+
client_tr_oper='send'
|
158
|
+
client_folder=self.options.get_option(:from_folder,:mandatory)
|
159
|
+
server_folder=self.transfer.destination_folder(client_tr_oper)
|
160
|
+
when :pull
|
161
|
+
client_tr_oper='receive'
|
162
|
+
client_folder=self.transfer.destination_folder(client_tr_oper)
|
163
|
+
server_folder=self.options.get_option(:from_folder,:mandatory)
|
164
|
+
end
|
165
|
+
client_node_file = @api_aoc.resolve_node_file(client_home_node_file,client_folder)
|
166
|
+
server_node_file = @api_aoc.resolve_node_file(server_home_node_file,server_folder)
|
167
|
+
# force node as transfer agent
|
168
|
+
@agents[:transfer].set_agent_instance(Fasp::Node.new(@api_aoc.get_node_api(client_node_file[:node_info],OnCloud::SCOPE_NODE_USER)))
|
169
|
+
# additional node to node TS info
|
170
|
+
add_ts={
|
171
|
+
'remote_access_key' => server_node_file[:node_info]['access_key'],
|
172
|
+
'destination_root_id' => server_node_file[:file_id],
|
173
|
+
'source_root_id' => client_node_file[:file_id]
|
174
|
+
}
|
175
|
+
return Main.result_transfer(transfer_start(OnCloud::FILES_APP,client_tr_oper,server_node_file,add_ts))
|
176
|
+
when :upload
|
177
|
+
node_file = @api_aoc.resolve_node_file(top_node_file,self.transfer.destination_folder('send'))
|
178
|
+
add_ts={'tags'=>{'aspera'=>{'files'=>{'parentCwd'=>"#{node_file[:node_info]['id']}:#{node_file[:file_id]}"}}}}
|
179
|
+
return Main.result_transfer(transfer_start(OnCloud::FILES_APP,'send',node_file,add_ts))
|
180
|
+
when :download
|
181
|
+
source_paths=self.transfer.ts_source_paths
|
182
|
+
# special case for AoC : all files must be in same folder
|
183
|
+
source_folder=source_paths.shift['source']
|
184
|
+
# if a single file: split into folder and path
|
185
|
+
if source_paths.empty?
|
186
|
+
source_folder=source_folder.split(OnCloud::PATH_SEPARATOR)
|
187
|
+
source_paths=[{'source'=>source_folder.pop}]
|
188
|
+
source_folder=source_folder.join(OnCloud::PATH_SEPARATOR)
|
189
|
+
end
|
190
|
+
node_file = @api_aoc.resolve_node_file(top_node_file,source_folder)
|
191
|
+
# override paths with just filename
|
192
|
+
add_ts={'tags'=>{'aspera'=>{'files'=>{'parentCwd'=>"#{node_file[:node_info]['id']}:#{node_file[:file_id]}"}}}}
|
193
|
+
add_ts.merge!({'paths'=>source_paths})
|
194
|
+
return Main.result_transfer(transfer_start(OnCloud::FILES_APP,'receive',node_file,add_ts))
|
195
|
+
when :http_node_download
|
196
|
+
source_paths=self.transfer.ts_source_paths
|
197
|
+
source_folder=source_paths.shift['source']
|
198
|
+
if source_paths.empty?
|
199
|
+
source_folder=source_folder.split(OnCloud::PATH_SEPARATOR)
|
200
|
+
source_paths=[{'source'=>source_folder.pop}]
|
201
|
+
source_folder=source_folder.join(OnCloud::PATH_SEPARATOR)
|
202
|
+
end
|
203
|
+
raise CliBadArgument,'one file at a time only in HTTP mode' if source_paths.length > 1
|
204
|
+
file_name = source_paths.first['source']
|
205
|
+
node_file = @api_aoc.resolve_node_file(top_node_file,File.join(source_folder,file_name))
|
206
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
|
207
|
+
node_api.call({:operation=>'GET',:subpath=>"files/#{node_file[:file_id]}/content",:save_to_file=>File.join(self.transfer.destination_folder('receive'),file_name)})
|
208
|
+
return Main.result_status("downloaded: #{file_name}")
|
209
|
+
when :v3
|
210
|
+
# Note: other "common" actions are unauthorized with user scope
|
211
|
+
command_legacy=self.options.get_next_command(Node::SIMPLE_ACTIONS)
|
212
|
+
# TODO: shall we support all methods here ? what if there is a link ?
|
213
|
+
node_api=@api_aoc.get_node_api(top_node_file[:node_info],OnCloud::SCOPE_NODE_USER)
|
214
|
+
return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: node_api)).execute_action(command_legacy)
|
215
|
+
when :file
|
216
|
+
fileid=self.options.get_next_argument('file id')
|
217
|
+
node_file = @api_aoc.resolve_node_file(top_node_file)
|
218
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
|
219
|
+
items=node_api.read("files/#{fileid}")[:data]
|
220
|
+
return {:type=>:single_object,:data=>items}
|
221
|
+
when :permissions
|
222
|
+
fileid=self.options.get_next_argument('file id')
|
223
|
+
node_file = @api_aoc.resolve_node_file(top_node_file)
|
224
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
|
225
|
+
command_perms=self.options.get_next_command([:show,:create])
|
226
|
+
case command_perms
|
227
|
+
when :show
|
228
|
+
items=node_api.read('permissions',{'include'=>['[]','access_level','permission_count'],'file_id'=>fileid,'inherited'=>false})[:data]
|
229
|
+
return {:type=>:object_list,:data=>items}
|
230
|
+
when :create
|
231
|
+
#value=self.options.get_next_argument('creation value')
|
232
|
+
set_workspace_info
|
233
|
+
access_id="ASPERA_ACCESS_KEY_ADMIN_WS_#{@workspace_id}"
|
234
|
+
node_file[:node_info]
|
235
|
+
params={
|
236
|
+
"file_id"=>fileid,
|
237
|
+
"access_type"=>"user",
|
238
|
+
"access_id"=>access_id,
|
239
|
+
"access_levels"=>["list","read","write","delete","mkdir","rename","preview"],
|
240
|
+
"tags"=>{
|
241
|
+
"aspera"=>{
|
242
|
+
"files"=>{
|
243
|
+
"workspace"=>{
|
244
|
+
"id"=>@workspace_id,
|
245
|
+
"workspace_name"=>@workspace_name,
|
246
|
+
"user_name"=>user_info['name'],
|
247
|
+
"shared_by_user_id"=>user_info['id'],
|
248
|
+
"shared_by_name"=>user_info['name'],
|
249
|
+
"shared_by_email"=>user_info['email'],
|
250
|
+
"shared_with_name"=>access_id,
|
251
|
+
"access_key"=>node_file[:node_info]['access_key'],
|
252
|
+
"node"=>node_file[:node_info]['name']}}}}}
|
253
|
+
item=node_api.create('permissions',params)[:data]
|
254
|
+
return {:type=>:single_object,:data=>item}
|
255
|
+
else raise "error"
|
256
|
+
end
|
257
|
+
end # command_repo
|
258
|
+
throw "ERR"
|
259
|
+
end # execute_node_gen4_command
|
260
|
+
|
261
|
+
# build constructor option list for OnCloud based on options of CLI
|
262
|
+
def oncloud_params(subpath)
|
263
|
+
# copy command line options to args
|
264
|
+
opt=[:link,:url,:auth,:client_id,:client_secret,:scope,:redirect_uri,:private_key,:username].inject({}){|m,i|m[i]=self.options.get_option(i,:optional);m}
|
265
|
+
opt[:subpath]=subpath
|
266
|
+
return opt
|
267
|
+
end
|
268
|
+
|
269
|
+
# Create a new AoC API REST object and set @api_aoc.
|
270
|
+
# Parameters based on command line options
|
271
|
+
# @return nil
|
272
|
+
def update_aoc_api
|
273
|
+
@api_aoc=OnCloud.new(oncloud_params('api/v1'))
|
274
|
+
# add access key secrets
|
275
|
+
@api_aoc.add_secrets(self.config.get_secrets)
|
276
|
+
return nil
|
277
|
+
end
|
278
|
+
|
279
|
+
# initialize apis and authentication
|
280
|
+
# set:
|
281
|
+
# @default_workspace_id
|
282
|
+
# @workspace_name
|
283
|
+
# @workspace_id
|
284
|
+
# @persist_ids
|
285
|
+
# returns nil
|
286
|
+
def set_workspace_info
|
287
|
+
if @api_aoc.params[:auth].has_key?(:url_token)
|
288
|
+
# TODO: can there be several in list ?
|
289
|
+
@url_token_data=@api_aoc.read('url_tokens')[:data].first
|
290
|
+
@default_workspace_id=@url_token_data['data']['workspace_id']
|
291
|
+
@persist_ids=[] # TODO : @url_token_data['id'] ?
|
292
|
+
else
|
293
|
+
@default_workspace_id=user_info['default_workspace_id']
|
294
|
+
@persist_ids=[user_info['id']]
|
295
|
+
end
|
296
|
+
|
297
|
+
ws_name=self.options.get_option(:workspace,:optional)
|
298
|
+
if ws_name.nil?
|
299
|
+
Log.log.debug("using default workspace".green)
|
300
|
+
if @default_workspace_id.eql?(nil)
|
301
|
+
raise CliError,"no default workspace defined for user, please specify workspace"
|
302
|
+
end
|
303
|
+
# get default workspace
|
304
|
+
@workspace_id=@default_workspace_id
|
305
|
+
else
|
306
|
+
# lookup another workspace
|
307
|
+
wss=@api_aoc.read("workspaces",{'q'=>ws_name})[:data]
|
308
|
+
wss=wss.select { |i| i['name'].eql?(ws_name) }
|
309
|
+
case wss.length
|
310
|
+
when 0
|
311
|
+
raise CliBadArgument,"no such workspace: #{ws_name}"
|
312
|
+
when 1
|
313
|
+
@workspace_id=wss.first['id']
|
314
|
+
else
|
315
|
+
raise "unexpected case"
|
316
|
+
end
|
317
|
+
end
|
318
|
+
@workspace_data=@api_aoc.read("workspaces/#{@workspace_id}")[:data]
|
319
|
+
Log.log.debug("workspace_id=#{@workspace_id},@workspace_data=#{@workspace_data}".red)
|
320
|
+
|
321
|
+
@workspace_name||=@workspace_data['name']
|
322
|
+
Log.log.info("current workspace is "+@workspace_name.red)
|
323
|
+
|
324
|
+
# display workspace
|
325
|
+
self.format.display_status("Current Workspace: #{@workspace_name.red}#{@workspace_id == @default_workspace_id ? ' (default)' : ''}")
|
326
|
+
return nil
|
327
|
+
end
|
328
|
+
|
329
|
+
# @home_node_file (hash with :node_info and :file_id)
|
330
|
+
def set_home_node_file
|
331
|
+
if !@url_token_data.nil?
|
332
|
+
assert_public_link_types(['view_shared_file'])
|
333
|
+
home_node_id=@url_token_data['data']['node_id']
|
334
|
+
home_file_id=@url_token_data['data']['file_id']
|
335
|
+
end
|
336
|
+
home_node_id||=@workspace_data['home_node_id']||@workspace_data['node_id']
|
337
|
+
home_file_id||=@workspace_data['home_file_id']
|
338
|
+
raise "node_id must be defined" if home_node_id.to_s.empty?
|
339
|
+
@home_node_file={
|
340
|
+
node_info: @api_aoc.read("nodes/#{home_node_id}")[:data],
|
341
|
+
file_id: home_file_id
|
342
|
+
}
|
343
|
+
@api_aoc.check_get_node_file(@home_node_file)
|
344
|
+
|
345
|
+
return nil
|
346
|
+
end
|
347
|
+
|
348
|
+
def do_bulk_operation(ids_or_one,success_msg,id_result='id',&do_action)
|
349
|
+
ids_or_one=[ids_or_one] unless self.options.get_option(:bulk)
|
350
|
+
raise "expecting Array" unless ids_or_one.is_a?(Array)
|
351
|
+
result_list=[]
|
352
|
+
ids_or_one.each do |id|
|
353
|
+
one={id_result=>id}
|
354
|
+
begin
|
355
|
+
res=do_action.call(id)
|
356
|
+
one=res if id.is_a?(Hash) # if block returns a has, let's use this
|
357
|
+
one['status']=success_msg
|
358
|
+
rescue => e
|
359
|
+
one['status']=e.to_s
|
360
|
+
end
|
361
|
+
result_list.push(one)
|
362
|
+
end
|
363
|
+
return {:type=>:object_list,:data=>result_list,:fields=>[id_result,'status']}
|
364
|
+
end
|
365
|
+
|
366
|
+
# package creation params can give just email, and full hash is created
|
367
|
+
def resolve_package_recipients(package_creation,recipient_list_field)
|
368
|
+
return unless package_creation.has_key?(recipient_list_field)
|
369
|
+
raise CliBadArgument,"#{recipient_list_field} must be an Array" unless package_creation[recipient_list_field].is_a?(Array)
|
370
|
+
new_user_option=self.options.get_option(:new_user_option,:mandatory)
|
371
|
+
resolved_list=[]
|
372
|
+
package_creation[recipient_list_field].each do |recipient_email_or_info|
|
373
|
+
case recipient_email_or_info
|
374
|
+
when Hash
|
375
|
+
raise 'recipient element hash shall have field id and type' unless recipient_email_or_info.has_key?('id') and recipient_email_or_info.has_key?('type')
|
376
|
+
# already provided all information ?
|
377
|
+
resolved_list.push(recipient_email_or_info)
|
378
|
+
when String
|
379
|
+
if recipient_email_or_info.include?('@')
|
380
|
+
# or need to resolve email
|
381
|
+
item_lookup=@api_aoc.read('contacts',{'current_workspace_id'=>@workspace_id,'q'=>recipient_email_or_info})[:data]
|
382
|
+
case item_lookup.length
|
383
|
+
when 1; recipient_user_id=item_lookup.first
|
384
|
+
when 0; recipient_user_id=@api_aoc.create('contacts',{'current_workspace_id'=>@workspace_id,'email'=>recipient_email_or_info}.merge(new_user_option))[:data]
|
385
|
+
else raise CliBadArgument,"multiple match for: #{recipient_email_or_info}"
|
386
|
+
end
|
387
|
+
resolved_list.push({'id'=>recipient_user_id['source_id'],'type'=>recipient_user_id['source_type']})
|
388
|
+
else
|
389
|
+
item_lookup=@api_aoc.read('dropboxes',{'current_workspace_id'=>@workspace_id,'q'=>recipient_email_or_info})[:data]
|
390
|
+
case item_lookup.length
|
391
|
+
when 1; recipient_user_id=item_lookup.first
|
392
|
+
when 0; raise "no such shared inbox in workspace #{@workspace_name}"
|
393
|
+
else raise CliBadArgument,"multiple match for: #{recipient_email_or_info}"
|
394
|
+
end
|
395
|
+
resolved_list.push({'id'=>recipient_user_id['id'],'type'=>'dropbox'})
|
396
|
+
end
|
397
|
+
else
|
398
|
+
raise "recipient item must be a String (email, shared inboc) or hash (id,type)"
|
399
|
+
end
|
400
|
+
end
|
401
|
+
package_creation[recipient_list_field]=resolved_list
|
402
|
+
end
|
403
|
+
|
404
|
+
def url_query(default)
|
405
|
+
query=self.options.get_option(:query,:optional)||default
|
406
|
+
Log.log.debug("Query=#{query}".bg_red)
|
407
|
+
begin
|
408
|
+
# check it is suitable
|
409
|
+
URI.encode_www_form(query) unless query.nil?
|
410
|
+
rescue => e
|
411
|
+
raise CliBadArgument,"query must be an extended value which can be encoded with URI.encode_www_form. Refer to manual. (#{e.message})"
|
412
|
+
end
|
413
|
+
return query
|
414
|
+
end
|
415
|
+
|
416
|
+
def assert_public_link_types(expected)
|
417
|
+
if !expected.include?(@url_token_data['purpose'])
|
418
|
+
raise CliBadArgument,"public link type is #{@url_token_data['purpose']} but action requires one of #{expected.join(',')}"
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
def execute_admin_action
|
423
|
+
self.options.set_option(:scope,OnCloud::SCOPE_FILES_ADMIN)
|
424
|
+
update_aoc_api
|
425
|
+
command_admin=self.options.get_next_command([ :ats, :resource, :usage_reports, :analytics, :subscription, :auth_providers ])
|
426
|
+
case command_admin
|
427
|
+
when :auth_providers
|
428
|
+
command_auth_prov=self.options.get_next_command([ :list, :update ])
|
429
|
+
case command_auth_prov
|
430
|
+
when :list
|
431
|
+
providers=@api_aoc.read('admin/auth_providers')[:data]
|
432
|
+
return {:type=>:object_list,:data=>providers}
|
433
|
+
when :update
|
434
|
+
end
|
435
|
+
when :subscription
|
436
|
+
org=@api_aoc.read('organization')[:data]
|
437
|
+
bss_api=OnCloud.new(oncloud_params('bss/platform'))
|
438
|
+
graphql_query="
|
439
|
+
query ($organization_id: ID!) {
|
440
|
+
aoc (organization_id: $organization_id) {
|
441
|
+
bssSubscription {
|
442
|
+
endDate
|
443
|
+
startDate
|
444
|
+
termMonths
|
445
|
+
plan
|
446
|
+
trial
|
447
|
+
termType
|
448
|
+
instances {
|
449
|
+
id
|
450
|
+
entitlements {
|
451
|
+
maxUsageMb
|
452
|
+
}
|
453
|
+
}
|
454
|
+
additionalStorageVolumeGb
|
455
|
+
additionalEgressVolumeGb
|
456
|
+
additionalUsers
|
457
|
+
term {
|
458
|
+
startDate
|
459
|
+
endDate
|
460
|
+
transferVolumeGb
|
461
|
+
egressVolumeGb
|
462
|
+
storageVolumeGb
|
463
|
+
}
|
464
|
+
paygoRate {
|
465
|
+
rate
|
466
|
+
currency
|
467
|
+
}
|
468
|
+
aocPlanData {
|
469
|
+
tier
|
470
|
+
trial
|
471
|
+
workspaces { max }
|
472
|
+
users {
|
473
|
+
planAmount
|
474
|
+
max
|
475
|
+
}
|
476
|
+
samlIntegration
|
477
|
+
activity
|
478
|
+
sharedInboxes
|
479
|
+
uniqueUrls
|
480
|
+
support
|
481
|
+
}
|
482
|
+
}
|
483
|
+
}
|
484
|
+
}
|
485
|
+
"
|
486
|
+
result=bss_api.create('graphql',{'variables'=>{'organization_id'=>org['id']},'query'=>graphql_query})[:data]['data']
|
487
|
+
return {:type=>:single_object,:data=>result['aoc']['bssSubscription']}
|
488
|
+
when :ats
|
489
|
+
ats_api = Rest.new(@api_aoc.params.deep_merge({
|
490
|
+
:base_url => @api_aoc.params[:base_url]+'/admin/ats/pub/v1',
|
491
|
+
:auth => {:scope => OnCloud::SCOPE_FILES_ADMIN_USER}
|
492
|
+
}))
|
493
|
+
return @ats.execute_action_gen(ats_api)
|
494
|
+
# when :search_nodes
|
495
|
+
# query=self.options.get_option(:query,:optional) || '*'
|
496
|
+
# nodes=@api_aoc.read("search_nodes",{'q'=>query})[:data]
|
497
|
+
# # simplify output
|
498
|
+
# nodes=nodes.map do |i|
|
499
|
+
# item=i['_source']
|
500
|
+
# item['score']=i['_score']
|
501
|
+
# nodedata=item['access_key_recursive_counts'].first
|
502
|
+
# item.delete('access_key_recursive_counts')
|
503
|
+
# item['node']=nodedata
|
504
|
+
# item
|
505
|
+
# end
|
506
|
+
# return {:type=>:object_list,:data=>nodes,:fields=>['host_name','node_status.cluster_id','node_status.node_id']}
|
507
|
+
when :analytics
|
508
|
+
analytics_api = Rest.new(@api_aoc.params.deep_merge({
|
509
|
+
:base_url => @api_aoc.params[:base_url].gsub('/api/v1','')+'/analytics/v2',
|
510
|
+
:auth => {:scope => OnCloud::SCOPE_FILES_ADMIN_USER}
|
511
|
+
}))
|
512
|
+
command_analytics=self.options.get_next_command([ :application_events, :transfers ])
|
513
|
+
case command_analytics
|
514
|
+
when :application_events
|
515
|
+
event_type=command_analytics.to_s
|
516
|
+
events=analytics_api.read("organizations/#{user_info['organization_id']}/#{event_type}")[:data][event_type]
|
517
|
+
return {:type=>:object_list,:data=>events}
|
518
|
+
when :transfers
|
519
|
+
event_type=command_analytics.to_s
|
520
|
+
filter_resource=self.options.get_option(:name,:optional) || 'organizations'
|
521
|
+
filter_id=self.options.get_option(:id,:optional) || case filter_resource
|
522
|
+
when 'organizations'; user_info['organization_id']
|
523
|
+
when 'users'; user_info['id']
|
524
|
+
when 'nodes'; user_info['id']
|
525
|
+
else raise "organizations or users for option --name"
|
526
|
+
end
|
527
|
+
#
|
528
|
+
filter=self.options.get_option(:query,:optional) || {}
|
529
|
+
filter['limit']||=100
|
530
|
+
if self.options.get_option(:once_only,:mandatory)
|
531
|
+
saved_date=[]
|
532
|
+
startdate_persistency=PersistencyActionOnce.new(
|
533
|
+
manager: @agents[:persistency],
|
534
|
+
data: saved_date,
|
535
|
+
ids: ['aoc_ana_date',self.options.get_option(:url,:mandatory),@workspace_name].push(filter_resource,filter_id))
|
536
|
+
start_datetime=saved_date.first
|
537
|
+
stop_datetime=Time.now.utc.strftime('%FT%T.%LZ')
|
538
|
+
#Log.log().error("start: #{start_datetime}")
|
539
|
+
#Log.log().error("end: #{stop_datetime}")
|
540
|
+
saved_date[0]=stop_datetime
|
541
|
+
filter['start_time'] = start_datetime unless start_datetime.nil?
|
542
|
+
filter['stop_time'] = stop_datetime
|
543
|
+
end
|
544
|
+
notification=self.options.get_option(:notify,:optional)
|
545
|
+
events=analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}",url_query(filter))[:data][event_type]
|
546
|
+
startdate_persistency.save unless startdate_persistency.nil?
|
547
|
+
if !notification.nil?
|
548
|
+
require 'erb'
|
549
|
+
events.each do |transfer|
|
550
|
+
email_to_send={}
|
551
|
+
notification.each do |k,v|
|
552
|
+
email_to_send[k.to_sym]=ERB.new(v).result(binding)
|
553
|
+
end
|
554
|
+
Log.log().error("send email: #{email_to_send}")
|
555
|
+
self.config.send_email(email_to_send)
|
556
|
+
end
|
557
|
+
end
|
558
|
+
return {:type=>:object_list,:data=>events}
|
559
|
+
end
|
560
|
+
when :resource
|
561
|
+
resource_type=self.options.get_next_argument('resource',[:self,:organization,:user,:group,:client,:contact,:dropbox,:node,:operation,:package,:saml_configuration, :workspace, :dropbox_membership,:short_link,:workspace_membership,'admin/apps_new'.to_sym,'admin/client_registration_token'.to_sym,'integrations/kms_profile'.to_sym])
|
562
|
+
resource_class_path=resource_type.to_s+case resource_type;when :dropbox;'es';when :self,:organization,'admin/apps_new'.to_sym;'';else; 's';end
|
563
|
+
singleton_object=[:self,:organization].include?(resource_type)
|
564
|
+
global_operations=[:create,:list]
|
565
|
+
supported_operations=[:show,:modify]
|
566
|
+
supported_operations.push(:delete,*global_operations) unless singleton_object
|
567
|
+
supported_operations.push(:v4,:v3) if resource_type.eql?(:node)
|
568
|
+
supported_operations.push(:set_pub_key) if resource_type.eql?(:client)
|
569
|
+
supported_operations.push(:shared_folders) if [:node,:workspace].include?(resource_type)
|
570
|
+
command=self.options.get_next_command(supported_operations)
|
571
|
+
|
572
|
+
# require identifier for non global commands
|
573
|
+
if !singleton_object and !global_operations.include?(command)
|
574
|
+
res_id=self.options.get_option(:id)
|
575
|
+
res_name=self.options.get_option(:name)
|
576
|
+
if res_id.nil? and res_name.nil? and resource_type.eql?(:node)
|
577
|
+
set_workspace_info
|
578
|
+
set_home_node_file
|
579
|
+
res_id=@home_node_file[:node_info]['id']
|
580
|
+
end
|
581
|
+
if !res_name.nil?
|
582
|
+
Log.log.warn("name overrides id") unless res_id.nil?
|
583
|
+
matching=@api_aoc.read(resource_class_path,{:q=>res_name})[:data]
|
584
|
+
raise CliError,"no resource match name" if matching.empty?
|
585
|
+
raise CliError,"several resources match name (#{matching.join(',')})" unless matching.length.eql?(1)
|
586
|
+
res_id=matching.first['id']
|
587
|
+
end
|
588
|
+
raise CliBadArgument,"provide either id or name" if res_id.nil?
|
589
|
+
resource_instance_path="#{resource_class_path}/#{res_id}"
|
590
|
+
end
|
591
|
+
resource_instance_path=resource_class_path if singleton_object
|
592
|
+
case command
|
593
|
+
when :create
|
594
|
+
id_result='id'
|
595
|
+
id_result='token' if resource_class_path.eql?('admin/client_registration_tokens')
|
596
|
+
# TODO: report inconsistency: creation url is !=, and does not return id.
|
597
|
+
resource_class_path='admin/client_registration/token' if resource_class_path.eql?('admin/client_registration_tokens')
|
598
|
+
list_or_one=self.options.get_next_argument("creation data (Hash)")
|
599
|
+
return do_bulk_operation(list_or_one,'created',id_result)do|params|
|
600
|
+
raise "expecting Hash" unless params.is_a?(Hash)
|
601
|
+
@api_aoc.create(resource_class_path,params)[:data]
|
602
|
+
end
|
603
|
+
when :list
|
604
|
+
default_fields=['id','name']
|
605
|
+
list_query=nil
|
606
|
+
case resource_type
|
607
|
+
when :node; default_fields.push('host','access_key')
|
608
|
+
when :operation; default_fields=nil
|
609
|
+
when :contact; default_fields=["email","name","source_id","source_type"]
|
610
|
+
when 'admin/apps_new'.to_sym; list_query={:organization_apps=>true};default_fields=['app_type','available']
|
611
|
+
when 'admin/client_registration_token'.to_sym; default_fields=['id','value','data.client_subject_scopes','created_at']
|
612
|
+
end
|
613
|
+
result=@api_aoc.read(resource_class_path,url_query(list_query))
|
614
|
+
self.format.display_status("Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}")
|
615
|
+
return {:type=>:object_list,:data=>result[:data],:fields=>default_fields}
|
616
|
+
when :show
|
617
|
+
object=@api_aoc.read(resource_instance_path)[:data]
|
618
|
+
fields=object.keys.select{|k|!k.eql?('certificate')}
|
619
|
+
return { :type=>:single_object, :data =>object, :fields=>fields }
|
620
|
+
when :modify
|
621
|
+
changes=self.options.get_next_argument('modified parameters (hash)')
|
622
|
+
@api_aoc.update(resource_instance_path,changes)
|
623
|
+
return Main.result_status('modified')
|
624
|
+
when :delete
|
625
|
+
return do_bulk_operation(res_id,'deleted')do|one_id|
|
626
|
+
@api_aoc.delete("#{resource_class_path}/#{one_id.to_s}")
|
627
|
+
{'id'=>one_id}
|
628
|
+
end
|
629
|
+
when :set_pub_key
|
630
|
+
# special : reads private and generate public
|
631
|
+
the_private_key=self.options.get_next_argument('private_key')
|
632
|
+
the_public_key=OpenSSL::PKey::RSA.new(the_private_key).public_key.to_s
|
633
|
+
@api_aoc.update(resource_instance_path,{:jwt_grant_enabled=>true, :public_key=>the_public_key})
|
634
|
+
return Main.result_success
|
635
|
+
when :v3,:v4
|
636
|
+
res_data=@api_aoc.read(resource_instance_path)[:data]
|
637
|
+
find_ak_secret(res_data['access_key'])
|
638
|
+
api_node=@api_aoc.get_node_api(res_data)
|
639
|
+
return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_node)).execute_action if command.eql?(:v3)
|
640
|
+
ak_data=api_node.call({:operation=>'GET',:subpath=>"access_keys/#{res_data['access_key']}",:headers=>{'Accept'=>'application/json'}})[:data]
|
641
|
+
return node_gen4_execute_action({node_info: res_data, file_id: ak_data['root_file_id']})
|
642
|
+
# when :info
|
643
|
+
# object=@api_aoc.read(resource_instance_path)[:data]
|
644
|
+
# access_key=object['access_key']
|
645
|
+
# match_list=@api_aoc.read('admin/search_nodes',{:q=>"access_key:\"#{access_key}\""})[:data]
|
646
|
+
# result=match_list.select{|i|i["_source"]["access_key_recursive_counts"].first["access_key"].eql?(access_key)}
|
647
|
+
# return Main.result_status('Private node') if result.empty?
|
648
|
+
# raise CliError,"more than one match" unless result.length.eql?(1)
|
649
|
+
# result=result.first["_source"]
|
650
|
+
# result.merge!(result['access_key_recursive_counts'].first)
|
651
|
+
# result.delete('access_key_recursive_counts')
|
652
|
+
# result.delete('token')
|
653
|
+
# return { :type=>:single_object, :data =>result}
|
654
|
+
when :shared_folders
|
655
|
+
read_params = case resource_type
|
656
|
+
when :workspace;{'access_id'=>"ASPERA_ACCESS_KEY_ADMIN_WS_#{res_id}",'access_type'=>'user'}
|
657
|
+
when :node;{'include'=>['[]','access_level','permission_count'],'created_by_id'=>"ASPERA_ACCESS_KEY_ADMIN"}
|
658
|
+
else raise "error"
|
659
|
+
end
|
660
|
+
res_data=@api_aoc.read("#{resource_class_path}/#{res_id}/permissions",read_params)[:data]
|
661
|
+
fields=case resource_type
|
662
|
+
when :node;['id','file_id','file.path','access_type']
|
663
|
+
when :workspace;['id','node_id','file_id','node_name','file.path','tags.aspera.files.workspace.share_as']
|
664
|
+
else raise "error"
|
665
|
+
end
|
666
|
+
return { :type=>:object_list, :data =>res_data , :fields=>fields}
|
667
|
+
else raise :ERROR
|
668
|
+
end
|
669
|
+
when :usage_reports
|
670
|
+
return {:type=>:object_list,:data=>@api_aoc.read("usage_reports",{:workspace_id=>@workspace_id})[:data]}
|
671
|
+
end
|
672
|
+
end
|
673
|
+
|
674
|
+
ACTIONS=[ :apiinfo, :bearer_token, :organization, :tier_restrictions, :user, :workspace, :packages, :files, :gateway, :admin, :automation, :servers]
|
675
|
+
|
676
|
+
def execute_action
|
677
|
+
command=self.options.get_next_command(ACTIONS)
|
678
|
+
case command
|
679
|
+
when :apiinfo
|
680
|
+
api_info={}
|
681
|
+
num=1
|
682
|
+
Resolv::DNS.open{|dns|dns.each_address('api.ibmaspera.com'){|a| api_info["api.#{num}"]=a;num+=1}}
|
683
|
+
return {:type=>:single_object,:data=>api_info}
|
684
|
+
when :bearer_token
|
685
|
+
return {:type=>:text,:data=>@api_aoc.oauth_token}
|
686
|
+
when :organization
|
687
|
+
return { :type=>:single_object, :data =>@api_aoc.read('organization')[:data] }
|
688
|
+
when :tier_restrictions
|
689
|
+
return { :type=>:single_object, :data =>@api_aoc.read('tier_restrictions')[:data] }
|
690
|
+
when :user
|
691
|
+
command=self.options.get_next_command([ :workspaces,:info,:shared_inboxes ])
|
692
|
+
case command
|
693
|
+
when :workspaces
|
694
|
+
return {:type=>:object_list,:data=>@api_aoc.read("workspaces")[:data],:fields=>['id','name']}
|
695
|
+
# when :settings
|
696
|
+
# return {:type=>:object_list,:data=>@api_aoc.read("client_settings/")[:data]}
|
697
|
+
when :shared_inboxes
|
698
|
+
query=url_query(nil)
|
699
|
+
if query.nil?
|
700
|
+
set_workspace_info
|
701
|
+
query={'embed[]'=>'dropbox','workspace_id'=>@workspace_id,'aggregate_permissions_by_dropbox'=>true,'sort'=>'dropbox_name'}
|
702
|
+
end
|
703
|
+
return {:type=>:object_list,:data=>@api_aoc.read("dropbox_memberships",query)[:data],:fields=>['dropbox_id','dropbox.name']}
|
704
|
+
when :info
|
705
|
+
command=self.options.get_next_command([ :show,:modify ])
|
706
|
+
case command
|
707
|
+
when :show
|
708
|
+
return { :type=>:single_object, :data =>user_info }
|
709
|
+
when :modify
|
710
|
+
@api_aoc.update("users/#{user_info['id']}",self.options.get_next_argument('modified parameters (hash)'))
|
711
|
+
return Main.result_status('modified')
|
712
|
+
end
|
713
|
+
end
|
714
|
+
when :workspace # show current workspace parameters
|
715
|
+
set_workspace_info
|
716
|
+
return { :type=>:single_object, :data =>@workspace_data }
|
717
|
+
when :packages
|
718
|
+
set_workspace_info if @url_token_data.nil?
|
719
|
+
command_pkg=self.options.get_next_command([ :send, :recv, :list, :show, :delete ])
|
720
|
+
case command_pkg
|
721
|
+
when :send
|
722
|
+
package_creation=self.options.get_option(:value,:mandatory)
|
723
|
+
raise CliBadArgument,"value must be hash, refer to doc" unless package_creation.is_a?(Hash)
|
724
|
+
|
725
|
+
if !@url_token_data.nil?
|
726
|
+
assert_public_link_types(['send_package_to_user','send_package_to_dropbox'])
|
727
|
+
box_type=@url_token_data['purpose'].split('_').last
|
728
|
+
package_creation['recipients']=[{'id'=>@url_token_data['data']["#{box_type}_id"],'type'=>box_type}]
|
729
|
+
@workspace_id=@url_token_data['data']['workspace_id']
|
730
|
+
end
|
731
|
+
|
732
|
+
package_creation['workspace_id']=@workspace_id
|
733
|
+
|
734
|
+
# list of files to include in package, optional
|
735
|
+
#package_creation['file_names']=self.transfer.ts_source_paths.map{|i|File.basename(i['source'])}
|
736
|
+
|
737
|
+
# lookup users
|
738
|
+
resolve_package_recipients(package_creation,'recipients')
|
739
|
+
resolve_package_recipients(package_creation,'bcc_recipients')
|
740
|
+
|
741
|
+
# create a new package with one file
|
742
|
+
package_info=@api_aoc.create('packages',package_creation)[:data]
|
743
|
+
|
744
|
+
# get node information for the node on which package must be created
|
745
|
+
node_info=@api_aoc.read("nodes/#{package_info['node_id']}")[:data]
|
746
|
+
|
747
|
+
# tell Aspera what to expect in package: 1 transfer (can also be done after transfer)
|
748
|
+
@api_aoc.update("packages/#{package_info['id']}",{'sent'=>true,'transfers_expected'=>1})[:data]
|
749
|
+
|
750
|
+
# execute transfer
|
751
|
+
node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
|
752
|
+
# raise esception if at least one error
|
753
|
+
Main.result_transfer(transfer_start(OnCloud::PACKAGES_APP,'send',node_file,OnCloud.package_tags(package_info,'upload')))
|
754
|
+
# return all info on package
|
755
|
+
return { :type=>:single_object, :data =>package_info}
|
756
|
+
when :recv
|
757
|
+
if !@url_token_data.nil?
|
758
|
+
assert_public_link_types(['view_received_package'])
|
759
|
+
self.options.set_option(:id,@url_token_data['data']['package_id'])
|
760
|
+
end
|
761
|
+
# scalar here
|
762
|
+
ids_to_download=self.options.get_option(:id,:mandatory)
|
763
|
+
skip_ids_data=[]
|
764
|
+
skip_ids_persistency=nil
|
765
|
+
if self.options.get_option(:once_only,:mandatory)
|
766
|
+
skip_ids_persistency=PersistencyActionOnce.new(
|
767
|
+
manager: @agents[:persistency],
|
768
|
+
data: skip_ids_data,
|
769
|
+
ids: ['aoc_recv',self.options.get_option(:url,:mandatory),@workspace_id].push(*@persist_ids))
|
770
|
+
end
|
771
|
+
if ids_to_download.eql?(VAL_ALL)
|
772
|
+
# get list of packages in inbox
|
773
|
+
package_info=@api_aoc.read('packages',{'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true,'workspace_id'=>@workspace_id})[:data]
|
774
|
+
# remove from list the ones already downloaded
|
775
|
+
ids_to_download=package_info.map{|e|e['id']}
|
776
|
+
# array here
|
777
|
+
ids_to_download.select!{|id|!skip_ids_data.include?(id)}
|
778
|
+
end # ALL
|
779
|
+
# list here
|
780
|
+
ids_to_download = [ids_to_download] unless ids_to_download.is_a?(Array)
|
781
|
+
result_transfer=[]
|
782
|
+
self.format.display_status("found #{ids_to_download.length} package(s).")
|
783
|
+
ids_to_download.each do |package_id|
|
784
|
+
package_info=@api_aoc.read("packages/#{package_id}")[:data]
|
785
|
+
node_info=@api_aoc.read("nodes/#{package_info['node_id']}")[:data]
|
786
|
+
self.format.display_status("downloading package: #{package_info['name']}")
|
787
|
+
add_ts={'paths'=>[{'source'=>'.'}]}
|
788
|
+
node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
|
789
|
+
statuses=transfer_start(OnCloud::PACKAGES_APP,'receive',node_file,OnCloud.package_tags(package_info,'download').merge(add_ts))
|
790
|
+
result_transfer.push({'package'=>package_id,'status'=>statuses.map{|i|i.to_s}.join(',')})
|
791
|
+
# update skip list only if all transfer sessions completed
|
792
|
+
if TransferAgent.session_status(statuses).eql?(:success)
|
793
|
+
skip_ids_data.push(package_id)
|
794
|
+
skip_ids_persistency.save unless skip_ids_persistency.nil?
|
795
|
+
end
|
796
|
+
end
|
797
|
+
return {:type=>:object_list,:data=>result_transfer}
|
798
|
+
when :show
|
799
|
+
package_id=self.options.get_next_argument('package ID')
|
800
|
+
package_info=@api_aoc.read("packages/#{package_id}")[:data]
|
801
|
+
return { :type=>:single_object, :data =>package_info }
|
802
|
+
when :list
|
803
|
+
# list all packages ('page'=>1,'per_page'=>10,)'sort'=>'-sent_at',
|
804
|
+
packages=@api_aoc.read("packages",{'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true,'workspace_id'=>@workspace_id})[:data]
|
805
|
+
return {:type=>:object_list,:data=>packages,:fields=>['id','name','bytes_transferred']}
|
806
|
+
when :delete
|
807
|
+
list_or_one=self.options.get_option(:id,:mandatory)
|
808
|
+
return do_bulk_operation(list_or_one,'deleted')do|id|
|
809
|
+
raise "expecting String identifier" unless id.is_a?(String) or id.is_a?(Integer)
|
810
|
+
@api_aoc.delete("packages/#{id}")[:data]
|
811
|
+
end
|
812
|
+
end
|
813
|
+
when :files
|
814
|
+
# get workspace related information
|
815
|
+
set_workspace_info
|
816
|
+
set_home_node_file
|
817
|
+
find_ak_secret(@home_node_file[:node_info]['access_key'],false)
|
818
|
+
command_repo=self.options.get_next_command(NODE4_COMMANDS.clone.concat([:short_link]))
|
819
|
+
case command_repo
|
820
|
+
when *NODE4_COMMANDS; return execute_node_gen4_command(command_repo,@home_node_file)
|
821
|
+
when :short_link
|
822
|
+
folder_dest=self.options.get_option(:to_folder,:optional)
|
823
|
+
value_option=self.options.get_option(:value,:optional)
|
824
|
+
case value_option
|
825
|
+
when 'public'
|
826
|
+
value_option={'purpose'=>'token_auth_redirection'}
|
827
|
+
when 'private'
|
828
|
+
value_option={'purpose'=>'shared_folder_auth_link'}
|
829
|
+
when NilClass,Hash
|
830
|
+
else raise "value must be either: public, private, Hash or nil"
|
831
|
+
end
|
832
|
+
create_params=nil
|
833
|
+
node_file=nil
|
834
|
+
if !folder_dest.nil?
|
835
|
+
node_file = @api_aoc.resolve_node_file(@home_node_file,folder_dest)
|
836
|
+
create_params={
|
837
|
+
file_id: node_file[:file_id],
|
838
|
+
node_id: node_file[:node_info]['id'],
|
839
|
+
workspace_id: @workspace_id
|
840
|
+
}
|
841
|
+
end
|
842
|
+
if !value_option.nil? and !create_params.nil?
|
843
|
+
case value_option['purpose']
|
844
|
+
when 'shared_folder_auth_link'
|
845
|
+
value_option['data']=create_params
|
846
|
+
value_option['user_selected_name']=nil
|
847
|
+
when 'token_auth_redirection'
|
848
|
+
create_params['name']=''
|
849
|
+
value_option['data']={
|
850
|
+
aoc: true,
|
851
|
+
url_token_data: {
|
852
|
+
data: create_params,
|
853
|
+
purpose: 'view_shared_file'
|
854
|
+
}
|
855
|
+
}
|
856
|
+
value_option['user_selected_name']=nil
|
857
|
+
else
|
858
|
+
raise "purpose must be one of: token_auth_redirection or shared_folder_auth_link"
|
859
|
+
end
|
860
|
+
self.options.set_option(:value,value_option)
|
861
|
+
end
|
862
|
+
result=self.entity_action(@api_aoc,'short_links',nil,:id,'self')
|
863
|
+
if result[:data].is_a?(Hash) and result[:data].has_key?('created_at') and result[:data]['resource_type'].eql?('UrlToken')
|
864
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
|
865
|
+
perm_data={
|
866
|
+
"file_id" =>node_file[:file_id],
|
867
|
+
"access_type" =>"user",
|
868
|
+
"access_id" =>result[:data]['resource_id'],
|
869
|
+
"access_levels"=>["delete","list","mkdir","preview","read","rename","write"],
|
870
|
+
"tags" =>{
|
871
|
+
"url_token" =>true,
|
872
|
+
"workspace_id" =>@workspace_id,
|
873
|
+
"workspace_name" =>@workspace_name,
|
874
|
+
"folder_name" =>"my folder",
|
875
|
+
"created_by_name" =>user_info['name'],
|
876
|
+
"created_by_email"=>user_info['email'],
|
877
|
+
"access_key" =>node_file[:node_info]['access_key'],
|
878
|
+
"node" =>node_file[:node_info]['host']
|
879
|
+
}
|
880
|
+
}
|
881
|
+
node_api.create("permissions?file_id=#{node_file[:file_id]}",perm_data)
|
882
|
+
end
|
883
|
+
return result
|
884
|
+
end # files command
|
885
|
+
throw "Error: shall not reach this line"
|
886
|
+
when :automation
|
887
|
+
Log.log.warn("BETA: work under progress")
|
888
|
+
# automation api is not in the same place
|
889
|
+
automation_rest_params=@api_aoc.params.clone
|
890
|
+
automation_rest_params[:base_url].gsub!('/api/','/automation/')
|
891
|
+
automation_api=Rest.new(automation_rest_params)
|
892
|
+
command_automation=self.options.get_next_command([ :workflows, :instances ])
|
893
|
+
case command_automation
|
894
|
+
when :instances
|
895
|
+
return self.entity_action(@api_aoc,'workflow_instances',nil,:id,nil)
|
896
|
+
when :workflows
|
897
|
+
wF_COMMANDS=Plugin::ALL_OPS.clone.push(:action,:launch)
|
898
|
+
wf_command=self.options.get_next_command(wF_COMMANDS)
|
899
|
+
case wf_command
|
900
|
+
when *Plugin::ALL_OPS
|
901
|
+
return self.entity_command(wf_command,automation_api,'workflows',nil,:id)
|
902
|
+
when :launch
|
903
|
+
wf_id=self.options.get_option(:id,:mandatory)
|
904
|
+
data=automation_api.create("workflows/#{wf_id}/launch",{})[:data]
|
905
|
+
return {:type=>:single_object,:data=>data}
|
906
|
+
when :action
|
907
|
+
wf_command=self.options.get_next_command([:list,:create,:show])
|
908
|
+
wf_id=self.options.get_option(:id,:mandatory)
|
909
|
+
step=automation_api.create('steps',{'workflow_id'=>wf_id})[:data]
|
910
|
+
automation_api.update("workflows/#{wf_id}",{'step_order'=>[step["id"]]})
|
911
|
+
action=automation_api.create('actions',{'step_id'=>step["id"],'type'=>'manual'})[:data]
|
912
|
+
automation_api.update("steps/#{step["id"]}",{'action_order'=>[action["id"]]})
|
913
|
+
wf=automation_api.read("workflows/#{wf_id}")[:data]
|
914
|
+
return {:type=>:single_object,:data=>wf}
|
915
|
+
end
|
916
|
+
end
|
917
|
+
when :gateway
|
918
|
+
set_workspace_info
|
919
|
+
require 'aspera/faspex_gw'
|
920
|
+
FaspexGW.new(@api_aoc,@workspace_id).start_server
|
921
|
+
when :admin
|
922
|
+
return execute_admin_action
|
923
|
+
when :servers
|
924
|
+
self.format.display_status("Beta feature")
|
925
|
+
server_api=Rest.new(base_url: 'https://eudemo.asperademo.com')
|
926
|
+
require 'json'
|
927
|
+
servers=JSON.parse(server_api.read('servers')[:data])
|
928
|
+
return {:type=>:object_list,:data=>servers}
|
929
|
+
else
|
930
|
+
raise "internal error: #{command}"
|
931
|
+
end # action
|
932
|
+
raise RuntimeError, "internal error: command shall return"
|
933
|
+
end
|
934
|
+
end # Aspera
|
935
|
+
end # Plugins
|
936
|
+
end # Cli
|
937
|
+
end # Aspera
|