aspera-cli 4.8.0 → 4.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.md +445 -160
- data/docs/test_env.conf +1 -5
- data/examples/dascli +1 -4
- data/examples/{transfer.rb → node.rb} +17 -46
- data/examples/server.rb +93 -0
- data/lib/aspera/aoc.rb +4 -2
- data/lib/aspera/ats_api.rb +3 -1
- data/lib/aspera/cli/extended_value.rb +1 -0
- data/lib/aspera/cli/formater.rb +3 -1
- data/lib/aspera/cli/info.rb +1 -1
- data/lib/aspera/cli/main.rb +14 -11
- data/lib/aspera/cli/manager.rb +4 -4
- data/lib/aspera/cli/plugin.rb +50 -9
- data/lib/aspera/cli/plugins/aoc.rb +88 -52
- data/lib/aspera/cli/plugins/config.rb +5 -0
- data/lib/aspera/cli/plugins/faspex.rb +5 -4
- data/lib/aspera/cli/plugins/node.rb +3 -2
- data/lib/aspera/cli/plugins/server.rb +7 -108
- data/lib/aspera/cli/plugins/shares.rb +21 -1
- data/lib/aspera/cli/transfer_agent.rb +21 -14
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/environment.rb +15 -2
- data/lib/aspera/fasp/agent_base.rb +9 -7
- data/lib/aspera/fasp/installation.rb +15 -19
- data/lib/aspera/fasp/parameters.rb +38 -30
- data/lib/aspera/fasp/parameters.yaml +69 -17
- data/lib/aspera/hash_ext.rb +14 -2
- data/lib/aspera/id_generator.rb +12 -10
- data/lib/aspera/keychain/encrypted_hash.rb +3 -3
- data/lib/aspera/log.rb +1 -1
- data/lib/aspera/nagios.rb +26 -19
- data/lib/aspera/oauth.rb +4 -4
- data/lib/aspera/open_application.rb +21 -19
- data/lib/aspera/persistency_folder.rb +3 -0
- data/lib/aspera/preview/image_error.png +0 -0
- data/lib/aspera/preview/video_error.png +0 -0
- data/lib/aspera/proxy_auto_config.rb +6 -4
- data/lib/aspera/rest_error_analyzer.rb +15 -13
- data/lib/aspera/rest_errors_aspera.rb +42 -40
- data/lib/aspera/secret_hider.rb +11 -5
- data/lib/aspera/ssh.rb +1 -0
- data/lib/aspera/uri_reader.rb +15 -13
- data.tar.gz.sig +0 -0
- metadata +4 -3
- metadata.gz.sig +0 -0
data/docs/test_env.conf
CHANGED
@@ -61,7 +61,6 @@ tst_faspex5_web:
|
|
61
61
|
client_secret: your value here
|
62
62
|
tst_faspex5:
|
63
63
|
url: your value here
|
64
|
-
insecure: your value here
|
65
64
|
auth: your value here
|
66
65
|
client_id: your value here
|
67
66
|
client_secret: your value here
|
@@ -98,7 +97,6 @@ tst_orch:
|
|
98
97
|
url: your value here
|
99
98
|
username: your value here
|
100
99
|
password: your value here
|
101
|
-
insecure: your value here
|
102
100
|
tst_ats:
|
103
101
|
ibm_api_key: your value here
|
104
102
|
ats_key: your value here
|
@@ -108,7 +106,6 @@ tst_bss:
|
|
108
106
|
password: your value here
|
109
107
|
tst_ak_preview:
|
110
108
|
url: your value here
|
111
|
-
insecure: your value here
|
112
109
|
username: your value here
|
113
110
|
password: your value here
|
114
111
|
mimemagic: your value here
|
@@ -116,7 +113,6 @@ tst_node_preview:
|
|
116
113
|
url: your value here
|
117
114
|
username: your value here
|
118
115
|
password: your value here
|
119
|
-
insecure: your value here
|
120
116
|
tst_cos:
|
121
117
|
apikey: your value here
|
122
118
|
crn: your value here
|
@@ -168,4 +164,4 @@ misc:
|
|
168
164
|
aoc_workspace2: your value here
|
169
165
|
http_gw_fqdn_port: your value here
|
170
166
|
tst_secrets:
|
171
|
-
|
167
|
+
eudemo-sedemo: your value here
|
data/examples/dascli
CHANGED
@@ -3,10 +3,8 @@
|
|
3
3
|
# by default take latest version
|
4
4
|
: ${version:=latest}
|
5
5
|
imgtag=$image:$version
|
6
|
-
# same location as in Dockerfile: generic top folder for apps
|
7
|
-
appdir=/usr/src/app
|
8
6
|
# same location as in Dockerfile: main config folder for ascli in container
|
9
|
-
ascli_home_container
|
7
|
+
ascli_home_container=/home/cliuser/.aspera/ascli
|
10
8
|
# convenience: special argument to install the image
|
11
9
|
case "$1" in install) docker pull $imgtag; exit 0; esac
|
12
10
|
# set default location for config folder on host if necessary
|
@@ -20,7 +18,6 @@ exec docker run \
|
|
20
18
|
--rm \
|
21
19
|
--tty \
|
22
20
|
--interactive \
|
23
|
-
--env ASCLI_HOME="$ascli_home_container" \
|
24
21
|
--volume "$ASCLI_HOME:$ascli_home_container" \
|
25
22
|
$imgtag \
|
26
23
|
ascli "$@"
|
@@ -15,11 +15,12 @@ require 'tmpdir'
|
|
15
15
|
|
16
16
|
tmpdir = ENV['tmp'] || Dir.tmpdir || '.'
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
raise 'Usage: PASSWORD=<password> $0 https://<address>:<port> <node user>' unless ARGV.length.eql?(2) && ENV.has_key?('PASSWORD')
|
19
|
+
|
20
|
+
# example : https://node_asperaweb@eudemo.asperademo.com:9092
|
21
|
+
node_uri = URI.parse(ARGV.shift)
|
22
|
+
node_user = ARGV.shift
|
23
|
+
node_pass = ENV['PASSWORD']
|
23
24
|
|
24
25
|
##############################################################
|
25
26
|
# generic initialisation : configuration of FaspManager
|
@@ -40,14 +41,14 @@ Aspera::Fasp::Installation.instance.ascp_path = ENV['ascp'] if ENV.has_key?('asc
|
|
40
41
|
# or install:
|
41
42
|
#
|
42
43
|
|
43
|
-
# get
|
44
|
-
|
44
|
+
# get Transfer Agent
|
45
|
+
transfer_agent = Aspera::Fasp::AgentDirect.new
|
45
46
|
|
46
47
|
# Note that it would also be possible to start transfers using other agents
|
47
48
|
#require 'aspera/fasp/connect'
|
48
|
-
#
|
49
|
+
#transfer_agent=Aspera::Fasp::Connect.new
|
49
50
|
#require 'aspera/fasp/node'
|
50
|
-
#
|
51
|
+
#transfer_agent=Aspera::Fasp::Node.new(Aspera::Rest.new(...))
|
51
52
|
|
52
53
|
##############################################################
|
53
54
|
# Optional : register an event listener
|
@@ -60,48 +61,18 @@ class MyListener < Aspera::Fasp::Listener
|
|
60
61
|
end
|
61
62
|
|
62
63
|
# register the sample listener to display events
|
63
|
-
|
64
|
-
|
65
|
-
##############################################################
|
66
|
-
# first example: download by SSH credentials
|
67
|
-
|
68
|
-
# manually build teansfer spec
|
69
|
-
transfer_spec = {
|
70
|
-
#'remote_host' =>'demo.asperasoft.com',
|
71
|
-
'remote_host' => URI.parse(DEMO_CONFIG[0]).host,
|
72
|
-
'ssh_port' => URI.parse(DEMO_CONFIG[0]).port,
|
73
|
-
'remote_user' => URI.parse(DEMO_CONFIG[0]).user,
|
74
|
-
'remote_password' => DEMO_CONFIG[2],
|
75
|
-
'direction' => 'receive',
|
76
|
-
'destination_root' => tmpdir,
|
77
|
-
'paths' => [{'source' => 'aspera-test-dir-tiny/200KB.1'}]
|
78
|
-
}
|
79
|
-
# start transfer in separate thread
|
80
|
-
# method returns as soon as transfer thread is created
|
81
|
-
# it des not wait for completion, or even for session startup
|
82
|
-
fasp_manager.start_transfer(transfer_spec)
|
83
|
-
|
84
|
-
# optional: helper method: wait for completion of transfers
|
85
|
-
# here we started a single transfer session (no multisession parameter)
|
86
|
-
# get array of status, one for each session (so, a single value array)
|
87
|
-
# each status is either :success or "error message"
|
88
|
-
transfer_result = fasp_manager.wait_for_transfers_completion
|
89
|
-
$stdout.puts(JSON.generate(transfer_result))
|
90
|
-
# get list of errors only
|
91
|
-
errors = transfer_result.reject{|i|i.eql?(:success)}
|
92
|
-
# the transfer was not success, as there is at least one error
|
93
|
-
raise "Error(s) occured: #{errors.join(',')}" if !errors.empty?
|
64
|
+
transfer_agent.add_listener(MyListener.new)
|
94
65
|
|
95
66
|
##############################################################
|
96
|
-
#
|
67
|
+
# Upload with node authorization
|
97
68
|
|
98
69
|
# create rest client for Node API on a public demo system, using public demo credentials
|
99
70
|
node_api = Aspera::Rest.new({
|
100
|
-
base_url:
|
71
|
+
base_url: node_uri.to_s,
|
101
72
|
auth: {
|
102
73
|
type: :basic,
|
103
|
-
username:
|
104
|
-
password:
|
74
|
+
username: node_user,
|
75
|
+
password: node_pass
|
105
76
|
}})
|
106
77
|
# define sample file(s) and destination folder
|
107
78
|
sources = ["#{tmpdir}/sample_file.txt"]
|
@@ -117,9 +88,9 @@ transfer_spec['paths'] = sources.map{|p|{'source' => p}}
|
|
117
88
|
# set authentication type to "token" (will trigger use of bypass SSH key)
|
118
89
|
transfer_spec['authentication'] = 'token'
|
119
90
|
# from here : same as example 1
|
120
|
-
|
91
|
+
transfer_agent.start_transfer(transfer_spec)
|
121
92
|
# optional: wait for transfer completion helper function to get events
|
122
|
-
transfer_result =
|
93
|
+
transfer_result = transfer_agent.wait_for_transfers_completion
|
123
94
|
errors = transfer_result.reject{|i|i.eql?(:success)}
|
124
95
|
# the transfer was not success, as there is at least one error
|
125
96
|
raise "Error(s) occured: #{errors.join(',')}" if !errors.empty?
|
data/examples/server.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Example: transfer a file using one of the provided transfer agents
|
5
|
+
# location of ascp can be specified with env var "ascp"
|
6
|
+
# temp folder can be specified with env var "tmp"
|
7
|
+
require 'aspera/fasp/agent_direct'
|
8
|
+
require 'aspera/fasp/listener'
|
9
|
+
require 'aspera/fasp/installation'
|
10
|
+
require 'aspera/log'
|
11
|
+
require 'aspera/rest'
|
12
|
+
require 'aspera/rest_errors_aspera'
|
13
|
+
require 'json'
|
14
|
+
require 'tmpdir'
|
15
|
+
|
16
|
+
tmpdir = ENV['tmp'] || Dir.tmpdir || '.'
|
17
|
+
|
18
|
+
raise 'Usage: PASSWORD=<password> $0 ssh://<address>:<port> <transfer user>' unless ARGV.length.eql?(2) && ENV.has_key?('PASSWORD')
|
19
|
+
|
20
|
+
# example : ssh://asperaweb@eudemo.asperademo.com:33001
|
21
|
+
server_uri = URI.parse(ARGV.shift)
|
22
|
+
server_user = ARGV.shift
|
23
|
+
server_pass = ENV['PASSWORD']
|
24
|
+
|
25
|
+
##############################################################
|
26
|
+
# generic initialisation : configuration of FaspManager
|
27
|
+
|
28
|
+
# set trace level for sample, set to :debug to see complete list of debug information
|
29
|
+
Aspera::Log.instance.level = :debug
|
30
|
+
|
31
|
+
# register aspera REST call error handlers
|
32
|
+
Aspera::RestErrorsAspera.register_handlers
|
33
|
+
|
34
|
+
# some required files are generated here (keys, certs)
|
35
|
+
Aspera::Fasp::Installation.instance.folder = tmpdir
|
36
|
+
# set path to your copy of ascp binary (else, let the system find)
|
37
|
+
Aspera::Fasp::Installation.instance.ascp_path = ENV['ascp'] if ENV.has_key?('ascp')
|
38
|
+
# another way is to detect installed products and use one of them
|
39
|
+
#Aspera::Fasp::Installation.instance.installed_products.each{|p|puts("found: #{p[:name]}")}
|
40
|
+
#Aspera::Fasp::Installation.instance.use_ascp_from_product('Aspera Connect')
|
41
|
+
# or install:
|
42
|
+
#
|
43
|
+
|
44
|
+
# get Transfer Agent
|
45
|
+
transfer_agent = Aspera::Fasp::AgentDirect.new
|
46
|
+
|
47
|
+
# Note that it would also be possible to start transfers using other agents
|
48
|
+
#require 'aspera/fasp/connect'
|
49
|
+
#transfer_agent=Aspera::Fasp::Connect.new
|
50
|
+
#require 'aspera/fasp/node'
|
51
|
+
#transfer_agent=Aspera::Fasp::Node.new(Aspera::Rest.new(...))
|
52
|
+
|
53
|
+
##############################################################
|
54
|
+
# Optional : register an event listener
|
55
|
+
|
56
|
+
# example of event listener that displays events on stdout
|
57
|
+
class MyListener < Aspera::Fasp::Listener
|
58
|
+
# this is the callback called during transfers, here we only display the received information
|
59
|
+
# but it could be used to get detailed error information, check "type" field is "ERROR"
|
60
|
+
def event_enhanced(data);$stdout.puts(JSON.generate(data));$stdout.flush;end
|
61
|
+
end
|
62
|
+
|
63
|
+
# register the sample listener to display events
|
64
|
+
transfer_agent.add_listener(MyListener.new)
|
65
|
+
|
66
|
+
##############################################################
|
67
|
+
# first example: download by SSH credentials
|
68
|
+
|
69
|
+
# manually build teansfer spec
|
70
|
+
transfer_spec = {
|
71
|
+
'remote_host' => server_uri.host,
|
72
|
+
'ssh_port' => server_uri.port,
|
73
|
+
'remote_user' => server_user,
|
74
|
+
'remote_password' => server_pass,
|
75
|
+
'direction' => 'receive',
|
76
|
+
'destination_root' => tmpdir,
|
77
|
+
'paths' => [{'source' => 'aspera-test-dir-tiny/200KB.1'}]
|
78
|
+
}
|
79
|
+
# start transfer in separate thread
|
80
|
+
# method returns as soon as transfer thread is created
|
81
|
+
# it des not wait for completion, or even for session startup
|
82
|
+
transfer_agent.start_transfer(transfer_spec)
|
83
|
+
|
84
|
+
# optional: helper method: wait for completion of transfers
|
85
|
+
# here we started a single transfer session (no multisession parameter)
|
86
|
+
# get array of status, one for each session (so, a single value array)
|
87
|
+
# each status is either :success or "error message"
|
88
|
+
transfer_result = transfer_agent.wait_for_transfers_completion
|
89
|
+
$stdout.puts(JSON.generate(transfer_result))
|
90
|
+
# get list of errors only
|
91
|
+
errors = transfer_result.reject{|i|i.eql?(:success)}
|
92
|
+
# the transfer was not success, as there is at least one error
|
93
|
+
raise "Error(s) occured: #{errors.join(',')}" if !errors.empty?
|
data/lib/aspera/aoc.rb
CHANGED
@@ -6,6 +6,7 @@ require 'aspera/hash_ext'
|
|
6
6
|
require 'aspera/data_repository'
|
7
7
|
require 'aspera/fasp/transfer_spec'
|
8
8
|
require 'base64'
|
9
|
+
require 'cgi'
|
9
10
|
|
10
11
|
Aspera::Oauth.register_token_creator(:aoc_pub_link,lambda{|o|
|
11
12
|
o.api.call({
|
@@ -315,7 +316,8 @@ module Aspera
|
|
315
316
|
end
|
316
317
|
else
|
317
318
|
# retrieve values from API
|
318
|
-
std_t_spec = node_api.create(
|
319
|
+
std_t_spec = node_api.create(
|
320
|
+
'files/download_setup',
|
319
321
|
{transfer_requests: [{ transfer_request: {paths: [{'source' => '/'}] } }] }
|
320
322
|
)[:data]['transfer_specs'].first['transfer_spec']
|
321
323
|
%w[remote_host remote_user ssh_port fasp_port].each {|i| transfer_spec[i] = std_t_spec[i]}
|
@@ -453,7 +455,7 @@ module Aspera
|
|
453
455
|
# @param options additional search options
|
454
456
|
def lookup_entity_by_name(entity_type,entity_name,options={})
|
455
457
|
# returns entities whose name contains value (case insensitive)
|
456
|
-
matching_items = read(entity_type,options.merge({'q' => entity_name}))[:data]
|
458
|
+
matching_items = read(entity_type,options.merge({'q' => CGI.escape(entity_name)}))[:data]
|
457
459
|
case matching_items.length
|
458
460
|
when 1 then return matching_items.first
|
459
461
|
when 0 then raise %Q{#{ENTITY_NOT_FOUND} #{entity_type}: "#{entity_name}"}
|
data/lib/aspera/ats_api.rb
CHANGED
data/lib/aspera/cli/formater.rb
CHANGED
@@ -14,7 +14,7 @@ module Aspera
|
|
14
14
|
CSV_RECORD_SEPARATOR = "\n"
|
15
15
|
CSV_FIELD_SEPARATOR = ','
|
16
16
|
# supported output formats
|
17
|
-
DISPLAY_FORMATS = %i[
|
17
|
+
DISPLAY_FORMATS = %i[text nagios ruby json jsonpp yaml table csv].freeze
|
18
18
|
# user output levels
|
19
19
|
DISPLAY_LEVELS = %i[info data error].freeze
|
20
20
|
CONF_OVERVIEW_KEYS=%w[config parameter value].freeze
|
@@ -147,6 +147,8 @@ module Aspera
|
|
147
147
|
# comma separated list in string format
|
148
148
|
user_asked_fields_list_str = @option_fields
|
149
149
|
case @option_format
|
150
|
+
when :text
|
151
|
+
display_message(:data,res_data.to_s)
|
150
152
|
when :nagios
|
151
153
|
Nagios.process(res_data)
|
152
154
|
when :ruby
|
data/lib/aspera/cli/info.rb
CHANGED
@@ -11,7 +11,7 @@ module Aspera
|
|
11
11
|
SRC_URL = 'https://github.com/IBM/aspera-cli'
|
12
12
|
# set this to warn in advance when minimum required ruby version will increase
|
13
13
|
# for example currently minimum version is 2.4 in gemspec, but future minimum will be 2.5
|
14
|
-
# set to
|
14
|
+
# set to current minimum if there is no deprecation
|
15
15
|
# the actual current minimum required version is in gemspec at required_ruby_version
|
16
16
|
RUBY_FUTURE_MINIMUM_VERSION = '2.5'
|
17
17
|
end
|
data/lib/aspera/cli/main.rb
CHANGED
@@ -16,6 +16,7 @@ require 'aspera/rest'
|
|
16
16
|
require 'aspera/nagios'
|
17
17
|
require 'aspera/colors'
|
18
18
|
require 'aspera/secret_hider'
|
19
|
+
require 'net/ssh'
|
19
20
|
|
20
21
|
module Aspera
|
21
22
|
module Cli
|
@@ -266,12 +267,12 @@ module Aspera
|
|
266
267
|
# early debug for parser
|
267
268
|
# Note: does not accept shortcuts
|
268
269
|
def early_debug_setup(argv)
|
269
|
-
Log.instance.program_name = PROGRAM_NAME
|
270
|
+
Aspera::Log.instance.program_name = PROGRAM_NAME
|
270
271
|
argv.each do |arg|
|
271
272
|
case arg
|
272
273
|
when '--' then break
|
273
|
-
when /^--log-level=(.*)/ then Log.instance.level = Regexp.last_match(1).to_sym
|
274
|
-
when /^--logger=(.*)/ then Log.instance.logger_type = Regexp.last_match(1).to_sym
|
274
|
+
when /^--log-level=(.*)/ then Aspera::Log.instance.level = Regexp.last_match(1).to_sym
|
275
|
+
when /^--logger=(.*)/ then Aspera::Log.instance.logger_type = Regexp.last_match(1).to_sym
|
275
276
|
end
|
276
277
|
end
|
277
278
|
end
|
@@ -334,19 +335,21 @@ module Aspera
|
|
334
335
|
@plugin_env[:formater].display_results(command_plugin.execute_action) if execute_command
|
335
336
|
# finish
|
336
337
|
@plugin_env[:transfer].shutdown
|
337
|
-
rescue
|
338
|
-
rescue
|
339
|
-
rescue
|
340
|
-
rescue
|
341
|
-
rescue
|
342
|
-
rescue
|
343
|
-
rescue
|
344
|
-
rescue
|
338
|
+
rescue Net::SSH::AuthenticationFailed => e; exception_info = {e: e,t: 'SSH',security: true}
|
339
|
+
rescue CliBadArgument => e; exception_info = {e: e,t: 'Argument',usage: true}
|
340
|
+
rescue CliNoSuchId => e; exception_info = {e: e,t: 'Identifier'}
|
341
|
+
rescue CliError => e; exception_info = {e: e,t: 'Tool',usage: true}
|
342
|
+
rescue Fasp::Error => e; exception_info = {e: e,t: 'FASP(ascp)'}
|
343
|
+
rescue Aspera::RestCallError => e; exception_info = {e: e,t: 'Rest'}
|
344
|
+
rescue SocketError => e; exception_info = {e: e,t: 'Network'}
|
345
|
+
rescue StandardError => e; exception_info = {e: e,t: 'Other',debug: true}
|
346
|
+
rescue Interrupt => e; exception_info = {e: e,t: 'Interruption',debug: true}
|
345
347
|
end
|
346
348
|
# cleanup file list files
|
347
349
|
TempFileManager.instance.cleanup
|
348
350
|
# 1- processing of error condition
|
349
351
|
unless exception_info.nil?
|
352
|
+
Log.log.warn(exception_info[:e].message) if Aspera::Log.instance.logger_type.eql?(:syslog) && exception_info[:security]
|
350
353
|
@plugin_env[:formater].display_message(:error,"#{ERROR_FLASH} #{exception_info[:t]}: #{exception_info[:e].message}")
|
351
354
|
@plugin_env[:formater].display_message(:error,'Use option -h to get help.') if exception_info[:usage]
|
352
355
|
if exception_info[:e].is_a?(Fasp::Error) && exception_info[:e].message.eql?('Remote host is not who we expected')
|
data/lib/aspera/cli/manager.rb
CHANGED
@@ -56,7 +56,7 @@ module Aspera
|
|
56
56
|
|
57
57
|
class << self
|
58
58
|
def enum_to_bool(enum)
|
59
|
-
raise "Value not valid for boolean: #{enum}/#{enum.class}" unless BOOLEAN_VALUES.include?(enum)
|
59
|
+
raise "Value not valid for boolean: [#{enum}]/#{enum.class}" unless BOOLEAN_VALUES.include?(enum)
|
60
60
|
return TRUE_VALUES.include?(enum)
|
61
61
|
end
|
62
62
|
|
@@ -210,7 +210,7 @@ module Aspera
|
|
210
210
|
end
|
211
211
|
value = ExtendedValue.instance.evaluate(value)
|
212
212
|
value = Manager.enum_to_bool(value) if @declared_options[option_symbol][:values].eql?(BOOLEAN_VALUES)
|
213
|
-
Log.log.debug("
|
213
|
+
Log.log.debug("(#{@declared_options[option_symbol][:type]}/#{where}) set #{option_symbol}=#{value}")
|
214
214
|
case @declared_options[option_symbol][:type]
|
215
215
|
when :accessor
|
216
216
|
@declared_options[option_symbol][:accessor].value = value
|
@@ -235,10 +235,10 @@ module Aspera
|
|
235
235
|
else
|
236
236
|
raise 'unknown type'
|
237
237
|
end
|
238
|
-
Log.log.debug("
|
238
|
+
Log.log.debug("(#{@declared_options[option_symbol][:type]}) get #{option_symbol}=#{result}")
|
239
239
|
end
|
240
240
|
# do not fail for manual generation if option mandatory but not set
|
241
|
-
result = '' if result.nil? && !@fail_on_missing_mandatory
|
241
|
+
result = '' if result.nil? && is_type.eql?(:mandatory) && !@fail_on_missing_mandatory
|
242
242
|
#Log.log.debug("interactive=#{@ask_missing_mandatory}")
|
243
243
|
if result.nil?
|
244
244
|
if !@ask_missing_mandatory
|
data/lib/aspera/cli/plugin.rb
CHANGED
@@ -4,9 +4,9 @@ module Aspera
|
|
4
4
|
module Cli
|
5
5
|
# base class for plugins modules
|
6
6
|
class Plugin
|
7
|
-
#
|
7
|
+
# operations without id
|
8
8
|
GLOBAL_OPS = %i[create list].freeze
|
9
|
-
#
|
9
|
+
# operations with id
|
10
10
|
INSTANCE_OPS = %i[modify delete show].freeze
|
11
11
|
ALL_OPS = [GLOBAL_OPS,INSTANCE_OPS].flatten.freeze
|
12
12
|
# max number of items for list command
|
@@ -34,6 +34,8 @@ module Aspera
|
|
34
34
|
options.add_opt_simple(:value,'extended value for create, update, list filter')
|
35
35
|
options.add_opt_simple(:property,'name of property to set')
|
36
36
|
options.add_opt_simple(:id,"resource identifier (#{INSTANCE_OPS.join(',')})")
|
37
|
+
options.add_opt_boolean(:bulk,'Bulk operation (only some)')
|
38
|
+
options.set_option(:bulk,:no)
|
37
39
|
options.parse_options!
|
38
40
|
@@options_created = true # rubocop:disable Style/ClassVars
|
39
41
|
end
|
@@ -46,8 +48,41 @@ module Aspera
|
|
46
48
|
end
|
47
49
|
|
48
50
|
# TODO
|
49
|
-
def get_next_id_command(instance_ops: INSTANCE_OPS,global_ops: GLOBAL_OPS)
|
50
|
-
|
51
|
+
#def get_next_id_command(instance_ops: INSTANCE_OPS,global_ops: GLOBAL_OPS)
|
52
|
+
# return get_next_argument('command',expected: command_list)
|
53
|
+
#end
|
54
|
+
|
55
|
+
# For create and delete operations: execute one actin or multiple if bulk is yes
|
56
|
+
# @param params either single id or hash, or array for bulk
|
57
|
+
# @param success_msg deleted or created
|
58
|
+
def do_bulk_operation(single_or_array,success_msg,id_result: 'id',fields: :default)
|
59
|
+
raise 'programming error: missing block' unless block_given?
|
60
|
+
params = options.get_option(:bulk) ? single_or_array : [single_or_array]
|
61
|
+
raise 'expecting Array for bulk operation' unless params.is_a?(Array)
|
62
|
+
Log.log.warn('Empty list given for bulk operation') if params.empty?
|
63
|
+
Log.dump(:bulk_create,params)
|
64
|
+
result_list = []
|
65
|
+
params.each do |param|
|
66
|
+
# init for delete
|
67
|
+
result = {id_result => param}
|
68
|
+
begin
|
69
|
+
# execute custom code
|
70
|
+
res = yield(param)
|
71
|
+
# if block returns a hash, let's use this (create)
|
72
|
+
result = res if param.is_a?(Hash)
|
73
|
+
result['status'] = success_msg
|
74
|
+
rescue StandardError => e
|
75
|
+
result['status'] = e.to_s
|
76
|
+
end
|
77
|
+
result_list.push(result)
|
78
|
+
end
|
79
|
+
display_fields = [id_result,'status']
|
80
|
+
if options.get_option(:bulk)
|
81
|
+
return {type: :object_list,data: result_list,fields: display_fields}
|
82
|
+
else
|
83
|
+
display_fields = fields unless fields.eql?(:default)
|
84
|
+
return {type: :single_object,data: result_list.first,fields: display_fields}
|
85
|
+
end
|
51
86
|
end
|
52
87
|
|
53
88
|
# @param command [Symbol] command to execute: create show list modify delete
|
@@ -56,6 +91,7 @@ module Aspera
|
|
56
91
|
# @param display_fields [Array] fields to display by default
|
57
92
|
# @param id_default [String] default identifier to use for existing entity commands (show, modify)
|
58
93
|
# @param item_list_key [String] result is in a subkey of the json
|
94
|
+
# @return result suitable for CLI result
|
59
95
|
def entity_command(command,rest_api,res_class_path,display_fields: nil,id_default: nil,item_list_key: false)
|
60
96
|
if INSTANCE_OPS.include?(command)
|
61
97
|
begin
|
@@ -76,7 +112,15 @@ module Aspera
|
|
76
112
|
end
|
77
113
|
case command
|
78
114
|
when :create
|
79
|
-
return
|
115
|
+
return do_bulk_operation(parameters,'created',fields: display_fields) do |params|
|
116
|
+
raise 'expecting Hash' unless params.is_a?(Hash)
|
117
|
+
rest_api.create(res_class_path,params)[:data]
|
118
|
+
end
|
119
|
+
when :delete
|
120
|
+
return do_bulk_operation(one_res_id,'deleted') do |one_id|
|
121
|
+
rest_api.delete("#{res_class_path}/#{one_id}")
|
122
|
+
{'id' => one_id}
|
123
|
+
end
|
80
124
|
when :show
|
81
125
|
return {type: :single_object, data: rest_api.read(one_res_path)[:data], fields: display_fields}
|
82
126
|
when :list
|
@@ -102,9 +146,6 @@ module Aspera
|
|
102
146
|
parameters = {property => parameters} unless property.nil?
|
103
147
|
rest_api.update(one_res_path,parameters)
|
104
148
|
return Main.result_status('modified')
|
105
|
-
when :delete
|
106
|
-
rest_api.delete(one_res_path)
|
107
|
-
return Main.result_status('deleted')
|
108
149
|
else
|
109
150
|
raise "unknown action: #{command}"
|
110
151
|
end
|
@@ -117,7 +158,7 @@ module Aspera
|
|
117
158
|
return entity_command(command,rest_api,res_class_path,**opts)
|
118
159
|
end
|
119
160
|
|
120
|
-
# shortcuts for plugin environment
|
161
|
+
# shortcuts helpers for plugin environment
|
121
162
|
def options; return @agents[:options];end
|
122
163
|
|
123
164
|
def transfer; return @agents[:transfer];end
|