aspera-cli 4.5.0 → 4.6.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.
- checksums.yaml +4 -4
- data/README.md +1063 -853
- data/docs/Makefile +3 -1
- data/docs/README.erb.md +1011 -808
- data/docs/doc_tools.rb +1 -1
- data/docs/test_env.conf +1 -0
- data/lib/aspera/aoc.rb +21 -0
- data/lib/aspera/ascmd.rb +14 -14
- data/lib/aspera/cli/formater.rb +8 -1
- data/lib/aspera/cli/main.rb +23 -21
- data/lib/aspera/cli/manager.rb +5 -1
- data/lib/aspera/cli/plugins/aoc.rb +94 -69
- data/lib/aspera/cli/plugins/config.rb +99 -49
- data/lib/aspera/cli/plugins/node.rb +55 -57
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/environment.rb +1 -1
- data/lib/aspera/faspex_gw.rb +2 -1
- data/lib/aspera/log.rb +1 -1
- data/lib/aspera/rest.rb +1 -0
- metadata +6 -3
data/docs/doc_tools.rb
CHANGED
@@ -32,7 +32,7 @@ def prstt;opprst.capitalize;end
|
|
32
32
|
|
33
33
|
def gemspec;Gem::Specification::load(ENV['GEMSPEC']) or raise "error loading #{ENV["GEMSPEC"]}";end
|
34
34
|
|
35
|
-
def geminstadd;gemspec.version.to_s.match(/\.[^0-9]/)?' --pre':'';end
|
35
|
+
def geminstadd;gemspec.version.to_s.match(/\.[^0-9]/) ? ' --pre' : '' ;end
|
36
36
|
|
37
37
|
# transfer spec description generation
|
38
38
|
def spec_table
|
data/docs/test_env.conf
CHANGED
@@ -143,6 +143,7 @@ misc:
|
|
143
143
|
aoc_publink_folder: your value here
|
144
144
|
aoc_shbx_ws: your value here
|
145
145
|
aoc_shbx_name: your value here
|
146
|
+
aoc_shbx_meta: your value here
|
146
147
|
aoc_node1_name: your value here
|
147
148
|
aoc_node1_secret: your value here
|
148
149
|
icos_bucket_key: your value here
|
data/lib/aspera/aoc.rb
CHANGED
@@ -428,5 +428,26 @@ module Aspera
|
|
428
428
|
return result
|
429
429
|
end
|
430
430
|
|
431
|
+
# @param entity_type path of entuty in API
|
432
|
+
# @param entity_name name of searched entity
|
433
|
+
# @param options additional search options
|
434
|
+
def lookup_entity_by_name(entity_type,entity_name,options={})
|
435
|
+
# returns entities whose name contains value (case insensitive)
|
436
|
+
matching_items=read(entity_type,options.merge({'q'=>entity_name}))[:data]
|
437
|
+
case matching_items.length
|
438
|
+
when 1; return matching_items.first
|
439
|
+
when 0; raise RuntimeError,'not found'
|
440
|
+
else
|
441
|
+
# multiple case insensitive partial matches, try case insensitive full match
|
442
|
+
# (anyway AoC does not allow creation of 2 entities with same case insensitive name)
|
443
|
+
icase_matches=matching_items.select{|i|i['name'].casecmp?(entity_name)}
|
444
|
+
case icase_matches.length
|
445
|
+
when 1; return icase_matches.first
|
446
|
+
when 0; raise "#{entity_type}: multiple case insensitive partial match for: \"#{entity_name}\": #{matching_items.map{|i|i['name']}} but no case insensitive full match. Please be more specific or give exact name."
|
447
|
+
else raise "Two entities cannot have the same case insensitive name: #{icase_matches.map{|i|i['name']}}"
|
448
|
+
end
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
431
452
|
end # AoC
|
432
453
|
end # Aspera
|
data/lib/aspera/ascmd.rb
CHANGED
@@ -62,19 +62,19 @@ module Aspera
|
|
62
62
|
# description of result structures (see ascmdtypes.h). Base types are big endian
|
63
63
|
# key = name of type
|
64
64
|
TYPES_DESCR={
|
65
|
-
:
|
66
|
-
:
|
67
|
-
:
|
68
|
-
:
|
69
|
-
:
|
70
|
-
:
|
71
|
-
:
|
72
|
-
:
|
73
|
-
:
|
74
|
-
:
|
75
|
-
:
|
76
|
-
:
|
77
|
-
:
|
65
|
+
result: {decode: :field_list,fields: [{name: :file,is_a: :stat},{name: :dir,is_a: :stat,special: :substruct},{name: :size,is_a: :size},{name: :error,is_a: :error},{name: :info,is_a: :info},{name: :success,is_a: nil,special: :return_true},{name: :exit,is_a: nil},{name: :df,is_a: :mnt,special: :restart_on_first},{name: :md5sum,is_a: :md5sum}]},
|
66
|
+
stat: {decode: :field_list,fields: [{name: :name,is_a: :zstr},{name: :size,is_a: :int64},{name: :mode,is_a: :int32,check: nil},{name: :zmode,is_a: :zstr},{name: :uid,is_a: :int32,check: nil},{name: :zuid,is_a: :zstr},{name: :gid,is_a: :int32,check: nil},{name: :zgid,is_a: :zstr},{name: :ctime,is_a: :epoch},{name: :zctime,is_a: :zstr},{name: :mtime,is_a: :epoch},{name: :zmtime,is_a: :zstr},{name: :atime,is_a: :epoch},{name: :zatime,is_a: :zstr},{name: :symlink,is_a: :zstr},{name: :errno,is_a: :int32},{name: :errstr,is_a: :zstr}]},
|
67
|
+
info: {decode: :field_list,fields: [{name: :platform,is_a: :zstr},{name: :version,is_a: :zstr},{name: :lang,is_a: :zstr},{name: :territory,is_a: :zstr},{name: :codeset,is_a: :zstr},{name: :lc_ctype,is_a: :zstr},{name: :lc_numeric,is_a: :zstr},{name: :lc_time,is_a: :zstr},{name: :lc_all,is_a: :zstr},{name: :dev,is_a: :zstr,special: :multiple},{name: :browse_caps,is_a: :zstr},{name: :protocol,is_a: :zstr}]},
|
68
|
+
size: {decode: :field_list,fields: [{name: :size,is_a: :int64},{name: :fcount,is_a: :int32},{name: :dcount,is_a: :int32},{name: :failed_fcount,is_a: :int32},{name: :failed_dcount,is_a: :int32}]},
|
69
|
+
error: {decode: :field_list,fields: [{name: :errno,is_a: :int32},{name: :errstr,is_a: :zstr}]},
|
70
|
+
mnt: {decode: :field_list,fields: [{name: :fs,is_a: :zstr},{name: :dir,is_a: :zstr},{name: :is_a,is_a: :zstr},{name: :total,is_a: :int64},{name: :used,is_a: :int64},{name: :free,is_a: :int64},{name: :fcount,is_a: :int64},{name: :errno,is_a: :int32},{name: :errstr,is_a: :zstr}]},
|
71
|
+
md5sum: {decode: :field_list,fields: [{name: :md5sum,is_a: :zstr}]},
|
72
|
+
int8: {decode: :base,unpack: 'C',size: 1},
|
73
|
+
int32: {decode: :base,unpack: 'L>',size: 4},
|
74
|
+
int64: {decode: :base,unpack: 'Q>',size: 8},
|
75
|
+
epoch: {decode: :base,unpack: 'Q>',size: 8},
|
76
|
+
zstr: {decode: :base,unpack: 'Z*'},
|
77
|
+
blist: {decode: :buffer_list}
|
78
78
|
}
|
79
79
|
|
80
80
|
# protocol enum start at one, but array index start at zero
|
@@ -113,7 +113,7 @@ module Aspera
|
|
113
113
|
length=parse(buffer,:int32,indent_level)
|
114
114
|
raise "ERROR:not enough bytes" if buffer.length < length
|
115
115
|
value=buffer.shift(length)
|
116
|
-
result.push({:btype
|
116
|
+
result.push({btype: btype,buffer: value})
|
117
117
|
Log.log.debug("#{" ."*indent_level}:buffer_list[#{result.length-1}] #{result.last}")
|
118
118
|
end
|
119
119
|
when :field_list
|
data/lib/aspera/cli/formater.rb
CHANGED
@@ -19,18 +19,21 @@ module Aspera
|
|
19
19
|
CSV_FIELD_SEPARATOR=","
|
20
20
|
|
21
21
|
private_constant :FIELDS_ALL,:FIELDS_DEFAULT,:DISPLAY_FORMATS,:DISPLAY_LEVELS,:CSV_RECORD_SEPARATOR,:CSV_FIELD_SEPARATOR
|
22
|
-
attr_accessor :option_flat_hash
|
22
|
+
attr_accessor :option_flat_hash,:option_transpose_single
|
23
23
|
|
24
24
|
def initialize(opt_mgr)
|
25
25
|
@option_flat_hash=true
|
26
|
+
@option_transpose_single=true
|
26
27
|
@opt_mgr=opt_mgr
|
27
28
|
@opt_mgr.set_obj_attr(:flat_hash,self,:option_flat_hash)
|
29
|
+
@opt_mgr.set_obj_attr(:transpose_single,self,:option_transpose_single)
|
28
30
|
@opt_mgr.add_opt_list(:format,DISPLAY_FORMATS,"output format")
|
29
31
|
@opt_mgr.add_opt_list(:display,DISPLAY_LEVELS,"output only some information")
|
30
32
|
@opt_mgr.add_opt_simple(:fields,"comma separated list of fields, or #{FIELDS_ALL}, or #{FIELDS_DEFAULT}")
|
31
33
|
@opt_mgr.add_opt_simple(:select,"select only some items in lists, extended value: hash (column, value)")
|
32
34
|
@opt_mgr.add_opt_simple(:table_style,"table display style")
|
33
35
|
@opt_mgr.add_opt_boolean(:flat_hash,"display hash values as additional keys")
|
36
|
+
@opt_mgr.add_opt_boolean(:transpose_single,"single object fields output vertically")
|
34
37
|
@opt_mgr.set_option(:format,:table)
|
35
38
|
@opt_mgr.set_option(:display,:info)
|
36
39
|
@opt_mgr.set_option(:fields,FIELDS_DEFAULT)
|
@@ -134,6 +137,10 @@ module Aspera
|
|
134
137
|
when :yaml
|
135
138
|
display_message(:data,res_data.to_yaml)
|
136
139
|
when :table,:csv
|
140
|
+
if !@option_transpose_single and results[:type].eql?(:single_object)
|
141
|
+
results[:type]=:object_list
|
142
|
+
res_data=[res_data]
|
143
|
+
end
|
137
144
|
case results[:type]
|
138
145
|
when :object_list # goes to table display
|
139
146
|
raise "internal error: unexpected type: #{res_data.class}, expecting Array" unless res_data.is_a?(Array)
|
data/lib/aspera/cli/main.rb
CHANGED
@@ -42,7 +42,7 @@ module Aspera
|
|
42
42
|
def set_http_parameters(http)
|
43
43
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @option_insecure
|
44
44
|
http.set_debug_output($stdout) if @option_rest_debug
|
45
|
-
raise
|
45
|
+
raise 'http_options expects Hash' unless @option_http_options.is_a?(Hash)
|
46
46
|
@option_http_options.each do |k,v|
|
47
47
|
method="#{k}=".to_sym
|
48
48
|
# check if accessor is a method of Net::HTTP
|
@@ -122,11 +122,11 @@ module Aspera
|
|
122
122
|
|
123
123
|
# define header for manual
|
124
124
|
def init_global_options
|
125
|
-
Log.log.debug(
|
126
|
-
@opt_mgr.add_opt_switch(:help,
|
127
|
-
@opt_mgr.add_opt_switch(:bash_comp,
|
128
|
-
@opt_mgr.add_opt_switch(:show_config,
|
129
|
-
@opt_mgr.add_opt_switch(:rest_debug,
|
125
|
+
Log.log.debug('init_global_options')
|
126
|
+
@opt_mgr.add_opt_switch(:help,'-h','Show this message.') { @option_help=true }
|
127
|
+
@opt_mgr.add_opt_switch(:bash_comp,'generate bash completion for command') { @bash_completion=true }
|
128
|
+
@opt_mgr.add_opt_switch(:show_config, 'Display parameters used for the provided action.') { @option_show_config=true }
|
129
|
+
@opt_mgr.add_opt_switch(:rest_debug,'-r','more debug for HTTP calls') { @option_rest_debug=true }
|
130
130
|
@opt_mgr.add_opt_switch(:version,'-v','display version') { @plugin_env[:formater].display_message(:data,Aspera::Cli::VERSION);Process.exit(0) }
|
131
131
|
@opt_mgr.add_opt_switch(:warnings,'-w','check for language warnings') { $VERBOSE=true }
|
132
132
|
# handler must be set before declaration
|
@@ -137,14 +137,14 @@ module Aspera
|
|
137
137
|
@opt_mgr.set_obj_attr(:http_options,self,:option_http_options)
|
138
138
|
@opt_mgr.set_obj_attr(:log_passwords,Log.instance,:log_passwords)
|
139
139
|
@opt_mgr.add_opt_list(:ui,OpenApplication.user_interfaces,'method to start browser')
|
140
|
-
@opt_mgr.add_opt_list(:log_level,Log.levels,
|
141
|
-
@opt_mgr.add_opt_list(:logger,Log.logtypes,
|
142
|
-
@opt_mgr.add_opt_simple(:lock_port,
|
143
|
-
@opt_mgr.add_opt_simple(:query,
|
144
|
-
@opt_mgr.add_opt_simple(:http_options,
|
145
|
-
@opt_mgr.add_opt_boolean(:insecure,
|
146
|
-
@opt_mgr.add_opt_boolean(:once_only,
|
147
|
-
@opt_mgr.add_opt_boolean(:log_passwords,
|
140
|
+
@opt_mgr.add_opt_list(:log_level,Log.levels,'Log level')
|
141
|
+
@opt_mgr.add_opt_list(:logger,Log.logtypes,'log method')
|
142
|
+
@opt_mgr.add_opt_simple(:lock_port,'prevent dual execution of a command, e.g. in cron')
|
143
|
+
@opt_mgr.add_opt_simple(:query,'additional filter for API calls (extended value) (some commands)')
|
144
|
+
@opt_mgr.add_opt_simple(:http_options,'options for http socket (extended value)')
|
145
|
+
@opt_mgr.add_opt_boolean(:insecure,'do not validate HTTPS certificate')
|
146
|
+
@opt_mgr.add_opt_boolean(:once_only,'process only new items (some commands)')
|
147
|
+
@opt_mgr.add_opt_boolean(:log_passwords,'show passwords in logs')
|
148
148
|
@opt_mgr.set_option(:ui,OpenApplication.default_gui_mode)
|
149
149
|
@opt_mgr.set_option(:once_only,:false)
|
150
150
|
# parse declared options
|
@@ -167,10 +167,10 @@ module Aspera
|
|
167
167
|
end
|
168
168
|
|
169
169
|
def generate_bash_completion
|
170
|
-
if @opt_mgr.get_next_argument(
|
170
|
+
if @opt_mgr.get_next_argument('',:multiple,:optional).nil?
|
171
171
|
@plugin_env[:config].plugins.keys.each{|p|puts p.to_s}
|
172
172
|
else
|
173
|
-
Log.log.warn(
|
173
|
+
Log.log.warn('only first level completion so far')
|
174
174
|
end
|
175
175
|
Process.exit(0)
|
176
176
|
end
|
@@ -186,7 +186,7 @@ module Aspera
|
|
186
186
|
def self.result_success; return result_status('complete'); end
|
187
187
|
|
188
188
|
def exit_with_usage(all_plugins)
|
189
|
-
Log.log.debug(
|
189
|
+
Log.log.debug('exit_with_usage'.bg_red)
|
190
190
|
# display main plugin options
|
191
191
|
@plugin_env[:formater].display_message(:error,@opt_mgr.parser)
|
192
192
|
if all_plugins
|
@@ -288,6 +288,8 @@ module Aspera
|
|
288
288
|
else
|
289
289
|
command_sym=@opt_mgr.get_next_command(@plugin_env[:config].plugins.keys.dup.unshift(:help))
|
290
290
|
end
|
291
|
+
# command will not be executed, but we need manual
|
292
|
+
@opt_mgr.fail_on_missing_mandatory=false if @option_help
|
291
293
|
# main plugin is not dynamically instanciated
|
292
294
|
case command_sym
|
293
295
|
when :help
|
@@ -335,8 +337,8 @@ module Aspera
|
|
335
337
|
TempFileManager.instance.cleanup
|
336
338
|
# 1- processing of error condition
|
337
339
|
unless exception_info.nil?
|
338
|
-
@plugin_env[:formater].display_message(:error,"ERROR:
|
339
|
-
@plugin_env[:formater].display_message(:error,
|
340
|
+
@plugin_env[:formater].display_message(:error,"#{'ERROR:'.bg_red.gray.blink} #{exception_info[1]}: #{exception_info[0].message}")
|
341
|
+
@plugin_env[:formater].display_message(:error,'Use option -h to get help.') if exception_info[2].eql?(:usage)
|
340
342
|
if exception_info.first.is_a?(Fasp::Error) and exception_info.first.message.eql?('Remote host is not who we expected')
|
341
343
|
@plugin_env[:formater].display_message(:error,"For this specific error, refer to:\n#{SRC_URL}#error-remote-host-is-not-who-we-expected\nAdd this to arguments:\n--ts=@json:'{\"sshfp\":null}'")
|
342
344
|
end
|
@@ -344,7 +346,7 @@ module Aspera
|
|
344
346
|
# 2- processing of command not processed (due to exception or bad command line)
|
345
347
|
if execute_command
|
346
348
|
@opt_mgr.final_errors.each do |msg|
|
347
|
-
@plugin_env[:formater].display_message(:error,"ERROR:
|
349
|
+
@plugin_env[:formater].display_message(:error,"#{'ERROR:'.bg_red.gray.blink} Argument: #{msg}")
|
348
350
|
# add code as exception if there is not already an error
|
349
351
|
exception_info=[Exception.new(msg),'UnusedArg'] if exception_info.nil?
|
350
352
|
end
|
@@ -355,7 +357,7 @@ module Aspera
|
|
355
357
|
# will force to show stack trace
|
356
358
|
raise exception_info[0]
|
357
359
|
else
|
358
|
-
@plugin_env[:formater].display_message(:error,
|
360
|
+
@plugin_env[:formater].display_message(:error,'Use --log-level=debug to get more details.') if exception_info[2].eql?(:debug)
|
359
361
|
Process.exit(1)
|
360
362
|
end
|
361
363
|
end
|
data/lib/aspera/cli/manager.rb
CHANGED
@@ -77,6 +77,7 @@ module Aspera
|
|
77
77
|
attr_reader :parser
|
78
78
|
attr_accessor :ask_missing_mandatory
|
79
79
|
attr_accessor :ask_missing_optional
|
80
|
+
attr_writer :fail_on_missing_mandatory
|
80
81
|
|
81
82
|
#
|
82
83
|
def initialize(program_name,argv=nil)
|
@@ -92,6 +93,7 @@ module Aspera
|
|
92
93
|
@ask_missing_mandatory=false # STDIN.isatty
|
93
94
|
# ask optional options if not provided and in interactive
|
94
95
|
@ask_missing_optional=false
|
96
|
+
@fail_on_missing_mandatory=true
|
95
97
|
# those must be set before parse, parse consumes those defined only
|
96
98
|
@unprocessed_defaults=[]
|
97
99
|
@unprocessed_env=[]
|
@@ -232,7 +234,7 @@ module Aspera
|
|
232
234
|
def set_option(option_symbol,value,where="default")
|
233
235
|
if ! @declared_options.has_key?(option_symbol)
|
234
236
|
Log.log.debug("set unknown option: #{option_symbol}")
|
235
|
-
raise "ERROR"
|
237
|
+
raise "ERROR: cannot set undeclared option"
|
236
238
|
#declare_option(option_symbol)
|
237
239
|
end
|
238
240
|
value=ExtendedValue.instance.evaluate(value)
|
@@ -267,6 +269,8 @@ module Aspera
|
|
267
269
|
end
|
268
270
|
Log.log.debug("get #{option_symbol} (#{@declared_options[option_symbol][:type]}) : #{result}")
|
269
271
|
end
|
272
|
+
# do not fail for manual generation if option mandatory but not set
|
273
|
+
result||='' unless @fail_on_missing_mandatory
|
270
274
|
Log.log.debug("interactive=#{@ask_missing_mandatory}")
|
271
275
|
if result.nil?
|
272
276
|
if !@ask_missing_mandatory
|
@@ -372,34 +372,34 @@ module Aspera
|
|
372
372
|
return {type: :object_list,data: result_list,fields: [id_result,'status']}
|
373
373
|
end
|
374
374
|
|
375
|
-
|
376
|
-
|
377
|
-
def
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
case icase_matches.length
|
388
|
-
when 1; return icase_matches.first
|
389
|
-
when 0; raise CliBadArgument,"#{entity_type}: multiple case insensitive partial match for: \"#{entity_name}\": #{matching_items.map{|i|i['name']}} but no case insensitive full match. Please be more specific or give exact name."
|
390
|
-
else raise "Two entities cannot have the same case insensitive name: #{icase_matches.map{|i|i['name']}}"
|
391
|
-
end
|
375
|
+
# get identifier or name from command line
|
376
|
+
# @return identifier
|
377
|
+
def get_resource_id_from_args(resource_class_path)
|
378
|
+
l_res_id=self.options.get_option(:id)
|
379
|
+
l_res_name=self.options.get_option(:name)
|
380
|
+
raise "Provide either option id or name, not both" unless l_res_id.nil? or l_res_name.nil?
|
381
|
+
# try to find item by name (single partial match or exact match)
|
382
|
+
l_res_id=@api_aoc.lookup_entity_by_name(resource_class_path,l_res_name)['id'] unless l_res_name.nil?
|
383
|
+
# if no name or id option, taken on command line (after command)
|
384
|
+
if l_res_id.nil?
|
385
|
+
l_res_id=self.options.get_next_argument('identifier')
|
386
|
+
l_res_id=@api_aoc.lookup_entity_by_name(resource_class_path,self.options.get_next_argument('identifier'))['id'] if l_res_id.eql?('name')
|
392
387
|
end
|
388
|
+
return l_res_id
|
389
|
+
end
|
390
|
+
|
391
|
+
def get_resource_path_from_args(resource_class_path)
|
392
|
+
return "#{resource_class_path}/#{get_resource_id_from_args(resource_class_path)}"
|
393
393
|
end
|
394
394
|
|
395
395
|
# package creation params can give just email, and full hash is created
|
396
|
-
def resolve_package_recipients(
|
397
|
-
return unless
|
398
|
-
raise CliBadArgument,"#{recipient_list_field} must be an Array" unless
|
396
|
+
def resolve_package_recipients(package_data,recipient_list_field)
|
397
|
+
return unless package_data.has_key?(recipient_list_field)
|
398
|
+
raise CliBadArgument,"#{recipient_list_field} must be an Array" unless package_data[recipient_list_field].is_a?(Array)
|
399
399
|
new_user_option=self.options.get_option(:new_user_option,:mandatory)
|
400
400
|
# list with resolved elements
|
401
401
|
resolved_list=[]
|
402
|
-
|
402
|
+
package_data[recipient_list_field].each do |short_recipient_info|
|
403
403
|
case short_recipient_info
|
404
404
|
when Hash # native api information, check keys
|
405
405
|
raise "#{recipient_list_field} element shall have fields: id and type" unless short_recipient_info.keys.sort.eql?(['id','type'])
|
@@ -407,9 +407,9 @@ module Aspera
|
|
407
407
|
# email: user, else dropbox
|
408
408
|
entity_type=short_recipient_info.include?('@') ? 'contacts' : 'dropboxes'
|
409
409
|
begin
|
410
|
-
full_recipient_info
|
410
|
+
full_recipient_info=@api_aoc.lookup_entity_by_name(entity_type,short_recipient_info,{'current_workspace_id'=>@workspace_id})
|
411
411
|
rescue RuntimeError => e
|
412
|
-
raise e unless e.message.eql?(
|
412
|
+
raise e unless e.message.eql?('not found')
|
413
413
|
if entity_type.eql?('contacts')
|
414
414
|
full_recipient_info=@api_aoc.create('contacts',{'current_workspace_id'=>@workspace_id,'email'=>short_recipient_info}.merge(new_user_option))[:data]
|
415
415
|
else
|
@@ -428,7 +428,27 @@ module Aspera
|
|
428
428
|
resolved_list.push(short_recipient_info)
|
429
429
|
end
|
430
430
|
# replace with resolved elements
|
431
|
-
|
431
|
+
package_data[recipient_list_field]=resolved_list
|
432
|
+
end
|
433
|
+
|
434
|
+
def normalize_metadata(pkg_data)
|
435
|
+
case pkg_data['metadata']
|
436
|
+
when NilClass;return
|
437
|
+
when Array;return
|
438
|
+
when Hash
|
439
|
+
api_meta=[]
|
440
|
+
pkg_data['metadata'].each do |k,v|
|
441
|
+
api_meta.push({
|
442
|
+
#'input_type' => 'single-dropdown',
|
443
|
+
'name' => k,
|
444
|
+
'values' => v.is_a?(Array) ? v : [v]
|
445
|
+
})
|
446
|
+
end
|
447
|
+
pkg_data['metadata']=api_meta
|
448
|
+
|
449
|
+
else raise "metadata field if not of expected type: #{pkg_meta.class}"
|
450
|
+
end
|
451
|
+
nil
|
432
452
|
end
|
433
453
|
|
434
454
|
# private
|
@@ -623,16 +643,7 @@ module Aspera
|
|
623
643
|
command=self.options.get_next_command(supported_operations)
|
624
644
|
# require identifier for non global commands
|
625
645
|
if !singleton_object and !global_operations.include?(command)
|
626
|
-
res_id=
|
627
|
-
res_name=self.options.get_option(:name)
|
628
|
-
raise "Provide id or name, not both" unless res_id.nil? or res_name.nil?
|
629
|
-
# try to find item by name (single partial match or exact match)
|
630
|
-
res_id=lookup_single(resource_class_path,res_name)['id'] if !res_name.nil?
|
631
|
-
# if no name or id option, taken on command line (after command)
|
632
|
-
if res_id.nil?
|
633
|
-
res_id=self.options.get_next_argument('identifier')
|
634
|
-
res_id=lookup_single(resource_class_path,self.options.get_next_argument('identifier'))['id'] if res_id.eql?('name')
|
635
|
-
end
|
646
|
+
res_id=get_resource_id_from_args(resource_class_path)
|
636
647
|
resource_instance_path="#{resource_class_path}/#{res_id}"
|
637
648
|
end
|
638
649
|
resource_instance_path=resource_class_path if singleton_object
|
@@ -697,7 +708,7 @@ module Aspera
|
|
697
708
|
when :node;{'include'=>['[]','access_level','permission_count'],'created_by_id'=>ID_AK_ADMIN}
|
698
709
|
else raise 'error'
|
699
710
|
end
|
700
|
-
res_data=@api_aoc.read("#{
|
711
|
+
res_data=@api_aoc.read("#{resource_instance_path}/permissions",read_params)[:data]
|
701
712
|
fields=case resource_type
|
702
713
|
when :node;['id','file_id','file.path','access_type']
|
703
714
|
when :workspace;['id','node_id','file_id','node_name','file.path','tags.aspera.files.workspace.share_as']
|
@@ -743,10 +754,11 @@ module Aspera
|
|
743
754
|
end
|
744
755
|
|
745
756
|
# must be public
|
746
|
-
ACTIONS=[ :reminder, :bearer_token, :organization, :tier_restrictions, :user, :
|
757
|
+
ACTIONS=[ :reminder, :servers, :bearer_token, :organization, :tier_restrictions, :user, :packages, :files, :admin, :automation, :gateway].freeze
|
747
758
|
|
748
759
|
def execute_action
|
749
760
|
command=self.options.get_next_command(ACTIONS)
|
761
|
+
# all commands require to login, but those 2
|
750
762
|
get_api unless [:reminder,:servers].include?(command)
|
751
763
|
case command
|
752
764
|
when :reminder
|
@@ -754,6 +766,8 @@ module Aspera
|
|
754
766
|
user_email=options.get_option(:username,:mandatory)
|
755
767
|
Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").create('organization_reminders',{email: user_email})[:data]
|
756
768
|
return Main.result_status("List of organizations user is member of, has been sent by e-mail to #{user_email}")
|
769
|
+
when :servers
|
770
|
+
return {type: :object_list,data: Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").read('servers')[:data]}
|
757
771
|
when :bearer_token
|
758
772
|
return {type: :text,data: @api_aoc.oauth_token}
|
759
773
|
when :organization
|
@@ -761,22 +775,19 @@ module Aspera
|
|
761
775
|
when :tier_restrictions
|
762
776
|
return { type: :single_object, data: @api_aoc.read('tier_restrictions')[:data] }
|
763
777
|
when :user
|
764
|
-
|
765
|
-
|
778
|
+
case self.options.get_next_command([ :workspaces,:profile ])
|
779
|
+
# when :settings
|
780
|
+
# return {type: :object_list,data: @api_aoc.read('client_settings/')[:data]}
|
766
781
|
when :workspaces
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
query=option_url_query(nil)
|
772
|
-
if query.nil?
|
782
|
+
case self.options.get_next_command([ :list,:current ])
|
783
|
+
when :list
|
784
|
+
return {type: :object_list,data: @api_aoc.read('workspaces')[:data],fields: ['id','name']}
|
785
|
+
when :current
|
773
786
|
set_workspace_info
|
774
|
-
|
787
|
+
return { type: :single_object, data: @workspace_data }
|
775
788
|
end
|
776
|
-
|
777
|
-
|
778
|
-
command=self.options.get_next_command([ :show,:modify ])
|
779
|
-
case command
|
789
|
+
when :profile
|
790
|
+
case self.options.get_next_command([ :show,:modify ])
|
780
791
|
when :show
|
781
792
|
return { type: :single_object, data: @api_aoc.user_info }
|
782
793
|
when :modify
|
@@ -784,45 +795,55 @@ module Aspera
|
|
784
795
|
return Main.result_status('modified')
|
785
796
|
end
|
786
797
|
end
|
787
|
-
when :workspace # show current workspace parameters
|
788
|
-
set_workspace_info
|
789
|
-
return { type: :single_object, data: @workspace_data }
|
790
798
|
when :packages
|
791
799
|
set_workspace_info if @url_token_data.nil?
|
792
|
-
|
793
|
-
|
800
|
+
case self.options.get_next_command([ :shared_inboxes, :send, :recv, :list, :show, :delete ])
|
801
|
+
when :shared_inboxes
|
802
|
+
case self.options.get_next_command([ :list, :show ])
|
803
|
+
when :list
|
804
|
+
query=option_url_query(nil)
|
805
|
+
if query.nil?
|
806
|
+
query={'embed[]'=>'dropbox','workspace_id'=>@workspace_id,'aggregate_permissions_by_dropbox'=>true,'sort'=>'dropbox_name'}
|
807
|
+
end
|
808
|
+
return {type: :object_list,data: @api_aoc.read('dropbox_memberships',query)[:data],fields: ['dropbox_id','dropbox.name']}
|
809
|
+
when :show
|
810
|
+
return {type: :single_object,data: @api_aoc.read(get_resource_path_from_args('dropboxes'),query)[:data]}
|
811
|
+
end
|
794
812
|
when :send
|
795
|
-
|
796
|
-
raise CliBadArgument,'value must be hash, refer to doc' unless
|
813
|
+
package_data=self.options.get_option(:value,:mandatory)
|
814
|
+
raise CliBadArgument,'value must be hash, refer to doc' unless package_data.is_a?(Hash)
|
797
815
|
|
798
816
|
if !@url_token_data.nil?
|
799
817
|
assert_public_link_types(['send_package_to_user','send_package_to_dropbox'])
|
800
818
|
box_type=@url_token_data['purpose'].split('_').last
|
801
|
-
|
819
|
+
package_data['recipients']=[{'id'=>@url_token_data['data']["#{box_type}_id"],'type'=>box_type}]
|
802
820
|
@workspace_id=@url_token_data['data']['workspace_id']
|
803
821
|
end
|
804
822
|
|
805
|
-
|
823
|
+
package_data['workspace_id']=@workspace_id
|
806
824
|
|
807
825
|
# list of files to include in package, optional
|
808
|
-
#
|
826
|
+
#package_data['file_names']=self.transfer.ts_source_paths.map{|i|File.basename(i['source'])}
|
809
827
|
|
810
828
|
# lookup users
|
811
|
-
resolve_package_recipients(
|
812
|
-
resolve_package_recipients(
|
829
|
+
resolve_package_recipients(package_data,'recipients')
|
830
|
+
resolve_package_recipients(package_data,'bcc_recipients')
|
831
|
+
normalize_metadata(package_data)
|
813
832
|
|
814
833
|
# create a new package container
|
815
|
-
package_info=@api_aoc.create('packages',
|
834
|
+
package_info=@api_aoc.create('packages',package_data)[:data]
|
816
835
|
|
817
836
|
# get node information for the node on which package must be created
|
818
837
|
node_info=@api_aoc.read("nodes/#{package_info['node_id']}")[:data]
|
819
838
|
|
820
|
-
# tell
|
839
|
+
# tell AoC what to expect in package: 1 transfer (can also be done after transfer)
|
840
|
+
# TODO: if multisession was used we should probably tell
|
841
|
+
# also, currently no "multi-source" , i.e. only from client-side files, unless "node" agent is used
|
821
842
|
@api_aoc.update("packages/#{package_info['id']}",{'sent'=>true,'transfers_expected'=>1})[:data]
|
822
843
|
|
823
|
-
#
|
844
|
+
# get destination: package folder
|
824
845
|
node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
|
825
|
-
# raise exception if at least one error
|
846
|
+
# execute transfer, raise exception if at least one error
|
826
847
|
Main.result_transfer(transfer_start(AoC::PACKAGES_APP,'send',node_file,AoC.package_tags(package_info,'upload')))
|
827
848
|
# return all info on package
|
828
849
|
return { type: :single_object, data: package_info}
|
@@ -874,6 +895,12 @@ module Aspera
|
|
874
895
|
return { type: :single_object, data: package_info }
|
875
896
|
when :list
|
876
897
|
query=option_url_query({'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true})
|
898
|
+
if query.has_key?('dropbox_name')
|
899
|
+
# convenience: specify name instead of id
|
900
|
+
raise 'not both dropbox_name and dropbox_id' if query.has_key?('dropbox_id')
|
901
|
+
query['dropbox_id']=@api_aoc.lookup_entity_by_name('dropboxes',query['dropbox_name'])['id']
|
902
|
+
query.delete('dropbox_name')
|
903
|
+
end
|
877
904
|
raise 'option must be Hash' unless query.is_a?(Hash)
|
878
905
|
query['workspace_id']||=@workspace_id
|
879
906
|
packages=@api_aoc.read('packages',query)[:data]
|
@@ -991,14 +1018,12 @@ module Aspera
|
|
991
1018
|
return {type: :single_object,data: wf}
|
992
1019
|
end
|
993
1020
|
end
|
1021
|
+
when :admin
|
1022
|
+
return execute_admin_action
|
994
1023
|
when :gateway
|
995
1024
|
set_workspace_info
|
996
1025
|
require 'aspera/faspex_gw'
|
997
1026
|
FaspexGW.new(@api_aoc,@workspace_id).start_server
|
998
|
-
when :admin
|
999
|
-
return execute_admin_action
|
1000
|
-
when :servers
|
1001
|
-
return {type: :object_list,data: Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").read('servers')[:data]}
|
1002
1027
|
else
|
1003
1028
|
raise "internal error: #{command}"
|
1004
1029
|
end # action
|