aspera-cli 4.7.0 → 4.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +1 -0
- data/README.md +844 -861
- data/bin/ascli +20 -1
- data/bin/asession +37 -34
- data/docs/test_env.conf +11 -3
- data/examples/aoc.rb +13 -12
- data/examples/dascli +26 -0
- data/examples/faspex4.rb +34 -29
- data/examples/transfer.rb +30 -29
- data/lib/aspera/aoc.rb +151 -143
- data/lib/aspera/ascmd.rb +56 -45
- data/lib/aspera/ats_api.rb +6 -5
- data/lib/aspera/cli/basic_auth_plugin.rb +18 -16
- data/lib/aspera/cli/extended_value.rb +32 -30
- data/lib/aspera/cli/formater.rb +103 -111
- data/lib/aspera/cli/info.rb +2 -1
- data/lib/aspera/cli/listener/line_dump.rb +1 -0
- data/lib/aspera/cli/listener/logger.rb +1 -0
- data/lib/aspera/cli/listener/progress.rb +13 -12
- data/lib/aspera/cli/listener/progress_multi.rb +21 -20
- data/lib/aspera/cli/main.rb +106 -89
- data/lib/aspera/cli/manager.rb +96 -85
- data/lib/aspera/cli/plugin.rb +50 -32
- data/lib/aspera/cli/plugins/alee.rb +6 -5
- data/lib/aspera/cli/plugins/aoc.rb +521 -426
- data/lib/aspera/cli/plugins/ats.rb +84 -83
- data/lib/aspera/cli/plugins/bss.rb +30 -27
- data/lib/aspera/cli/plugins/config.rb +483 -397
- data/lib/aspera/cli/plugins/console.rb +17 -15
- data/lib/aspera/cli/plugins/cos.rb +26 -35
- data/lib/aspera/cli/plugins/faspex.rb +201 -168
- data/lib/aspera/cli/plugins/faspex5.rb +109 -74
- data/lib/aspera/cli/plugins/node.rb +378 -189
- data/lib/aspera/cli/plugins/orchestrator.rb +71 -65
- data/lib/aspera/cli/plugins/preview.rb +131 -122
- data/lib/aspera/cli/plugins/server.rb +94 -93
- data/lib/aspera/cli/plugins/shares.rb +42 -28
- data/lib/aspera/cli/plugins/sync.rb +15 -14
- data/lib/aspera/cli/transfer_agent.rb +56 -52
- data/lib/aspera/cli/version.rb +2 -1
- data/lib/aspera/colors.rb +29 -28
- data/lib/aspera/command_line_builder.rb +50 -43
- data/lib/aspera/cos_node.rb +64 -38
- data/lib/aspera/data_repository.rb +1 -0
- data/lib/aspera/environment.rb +18 -8
- data/lib/aspera/fasp/agent_base.rb +26 -23
- data/lib/aspera/fasp/agent_connect.rb +35 -30
- data/lib/aspera/fasp/agent_direct.rb +68 -60
- data/lib/aspera/fasp/agent_httpgw.rb +71 -64
- data/lib/aspera/fasp/agent_node.rb +24 -23
- data/lib/aspera/fasp/agent_trsdk.rb +19 -20
- data/lib/aspera/fasp/error.rb +2 -1
- data/lib/aspera/fasp/error_info.rb +79 -68
- data/lib/aspera/fasp/installation.rb +122 -114
- data/lib/aspera/fasp/listener.rb +1 -0
- data/lib/aspera/fasp/parameters.rb +44 -41
- data/lib/aspera/fasp/resume_policy.rb +14 -11
- data/lib/aspera/fasp/transfer_spec.rb +6 -5
- data/lib/aspera/fasp/uri.rb +25 -24
- data/lib/aspera/faspex_gw.rb +83 -72
- data/lib/aspera/hash_ext.rb +10 -12
- data/lib/aspera/id_generator.rb +8 -7
- data/lib/aspera/keychain/encrypted_hash.rb +60 -45
- data/lib/aspera/keychain/macos_security.rb +26 -24
- data/lib/aspera/log.rb +34 -38
- data/lib/aspera/nagios.rb +14 -13
- data/lib/aspera/node.rb +19 -19
- data/lib/aspera/oauth.rb +121 -101
- data/lib/aspera/open_application.rb +6 -5
- data/lib/aspera/persistency_action_once.rb +9 -8
- data/lib/aspera/persistency_folder.rb +10 -9
- data/lib/aspera/preview/file_types.rb +261 -266
- data/lib/aspera/preview/generator.rb +74 -73
- data/lib/aspera/preview/image_error.png +0 -0
- data/lib/aspera/preview/options.rb +7 -6
- data/lib/aspera/preview/utils.rb +30 -33
- data/lib/aspera/preview/video_error.png +0 -0
- data/lib/aspera/proxy_auto_config.rb +25 -23
- data/lib/aspera/rest.rb +73 -74
- data/lib/aspera/rest_call_error.rb +1 -0
- data/lib/aspera/rest_error_analyzer.rb +11 -9
- data/lib/aspera/rest_errors_aspera.rb +5 -4
- data/lib/aspera/secret_hider.rb +68 -0
- data/lib/aspera/ssh.rb +12 -10
- data/lib/aspera/sync.rb +49 -47
- data/lib/aspera/temp_file_manager.rb +7 -5
- data/lib/aspera/timer_limiter.rb +9 -8
- data/lib/aspera/uri_reader.rb +11 -14
- data/lib/aspera/web_auth.rb +17 -15
- data.tar.gz.sig +0 -0
- metadata +117 -34
- metadata.gz.sig +2 -0
- data/bin/dascli +0 -13
data/lib/aspera/cli/manager.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'aspera/colors'
|
3
4
|
require 'aspera/log'
|
4
5
|
require 'aspera/cli/extended_value'
|
@@ -15,7 +16,7 @@ module Aspera
|
|
15
16
|
|
16
17
|
class CliNoSuchId < CliError
|
17
18
|
def initialize(res_type,res_id)
|
18
|
-
msg="No such #{res_type} identifier: #{res_id}"
|
19
|
+
msg = "No such #{res_type} identifier: #{res_id}"
|
19
20
|
super(msg)
|
20
21
|
end
|
21
22
|
end
|
@@ -25,8 +26,8 @@ module Aspera
|
|
25
26
|
#attr_accessor :object
|
26
27
|
#attr_accessor :attr_symb
|
27
28
|
def initialize(object,attr_symb)
|
28
|
-
@object=object
|
29
|
-
@attr_symb=attr_symb
|
29
|
+
@object = object
|
30
|
+
@attr_symb = attr_symb
|
30
31
|
end
|
31
32
|
|
32
33
|
def value
|
@@ -43,15 +44,15 @@ module Aspera
|
|
43
44
|
# resolves on extended value syntax
|
44
45
|
class Manager
|
45
46
|
# boolean options are set to true/false from the following values
|
46
|
-
TRUE_VALUES=[:yes,true].freeze
|
47
|
-
BOOLEAN_VALUES=[TRUE_VALUES,:no,false].flatten.freeze
|
48
|
-
BOOLEAN_SIMPLE=[
|
47
|
+
TRUE_VALUES = [:yes,true].freeze
|
48
|
+
BOOLEAN_VALUES = [TRUE_VALUES,:no,false].flatten.freeze
|
49
|
+
BOOLEAN_SIMPLE = %i[yes no].freeze
|
49
50
|
# option name separator on command line
|
50
|
-
OPTION_SEP_LINE='-'
|
51
|
+
OPTION_SEP_LINE = '-'
|
51
52
|
# option name separator in code (symbol)
|
52
|
-
OPTION_SEP_NAME='_'
|
53
|
+
OPTION_SEP_NAME = '_'
|
53
54
|
|
54
|
-
private_constant :TRUE_VALUES,:BOOLEAN_VALUES,:
|
55
|
+
private_constant :TRUE_VALUES,:BOOLEAN_VALUES,:OPTION_SEP_LINE,:OPTION_SEP_NAME
|
55
56
|
|
56
57
|
class << self
|
57
58
|
def enum_to_bool(enum)
|
@@ -66,9 +67,9 @@ module Aspera
|
|
66
67
|
# find shortened string value in allowed symbol list
|
67
68
|
def get_from_list(shortval,descr,allowed_values)
|
68
69
|
# we accept shortcuts
|
69
|
-
matching_exact=allowed_values.select{|i| i.to_s.eql?(shortval)}
|
70
|
+
matching_exact = allowed_values.select{|i| i.to_s.eql?(shortval)}
|
70
71
|
return matching_exact.first if matching_exact.length == 1
|
71
|
-
matching=allowed_values.select{|i| i.to_s.start_with?(shortval)}
|
72
|
+
matching = allowed_values.select{|i| i.to_s.start_with?(shortval)}
|
72
73
|
raise CliBadArgument,bad_arg_message_multi("unknown value for #{descr}: #{shortval}",allowed_values) if matching.empty?
|
73
74
|
raise CliBadArgument,bad_arg_message_multi("ambigous shortcut for #{descr}: #{shortval}",matching) unless matching.length.eql?(1)
|
74
75
|
return enum_to_bool(matching.first) if allowed_values.eql?(BOOLEAN_VALUES)
|
@@ -84,36 +85,36 @@ module Aspera
|
|
84
85
|
attr_accessor :ask_missing_mandatory, :ask_missing_optional
|
85
86
|
attr_writer :fail_on_missing_mandatory
|
86
87
|
|
87
|
-
def initialize(program_name,argv
|
88
|
+
def initialize(program_name,argv: nil)
|
88
89
|
# command line values not starting with '-'
|
89
|
-
@unprocessed_cmd_line_arguments=[]
|
90
|
+
@unprocessed_cmd_line_arguments = []
|
90
91
|
# command line values starting with '-'
|
91
|
-
@unprocessed_cmd_line_options=[]
|
92
|
+
@unprocessed_cmd_line_options = []
|
92
93
|
# a copy of all initial options
|
93
|
-
@initial_cli_options=[]
|
94
|
+
@initial_cli_options = []
|
94
95
|
# option description: key = option symbol, value=hash, :type, :accessor, :value, :accepted
|
95
|
-
@declared_options={}
|
96
|
+
@declared_options = {}
|
96
97
|
# do we ask missing options and arguments to user ?
|
97
|
-
@ask_missing_mandatory=false # STDIN.isatty
|
98
|
+
@ask_missing_mandatory = false # STDIN.isatty
|
98
99
|
# ask optional options if not provided and in interactive
|
99
|
-
@ask_missing_optional=false
|
100
|
-
@fail_on_missing_mandatory=true
|
100
|
+
@ask_missing_optional = false
|
101
|
+
@fail_on_missing_mandatory = true
|
101
102
|
# those must be set before parse, parse consumes those defined only
|
102
|
-
@unprocessed_defaults=[]
|
103
|
-
@unprocessed_env=[]
|
103
|
+
@unprocessed_defaults = []
|
104
|
+
@unprocessed_env = []
|
104
105
|
# Note: was initially inherited but it is prefered to have specific methods
|
105
|
-
@parser=OptionParser.new
|
106
|
-
@parser.program_name=program_name
|
106
|
+
@parser = OptionParser.new
|
107
|
+
@parser.program_name = program_name
|
107
108
|
# options can also be provided by env vars : --param-name -> ASLMCLI_PARAM_NAME
|
108
|
-
env_prefix=program_name.upcase+OPTION_SEP_NAME
|
109
|
+
env_prefix = program_name.upcase + OPTION_SEP_NAME
|
109
110
|
ENV.each do |k,v|
|
110
111
|
if k.start_with?(env_prefix)
|
111
112
|
@unprocessed_env.push([k[env_prefix.length..-1].downcase.to_sym,v])
|
112
113
|
end
|
113
114
|
end
|
114
115
|
Log.log.debug("env=#{@unprocessed_env}".red)
|
115
|
-
@unprocessed_cmd_line_options=[]
|
116
|
-
@unprocessed_cmd_line_arguments=[]
|
116
|
+
@unprocessed_cmd_line_options = []
|
117
|
+
@unprocessed_cmd_line_arguments = []
|
117
118
|
# argv is nil when help is generated for every plugin
|
118
119
|
unless argv.nil?
|
119
120
|
@parser.separator('')
|
@@ -123,12 +124,12 @@ module Aspera
|
|
123
124
|
add_opt_boolean(:interactive,'use interactive input of missing params')
|
124
125
|
add_opt_boolean(:ask_options,'ask even optional options')
|
125
126
|
parse_options!
|
126
|
-
process_options=true
|
127
|
+
process_options = true
|
127
128
|
while !argv.empty?
|
128
|
-
value=argv.shift
|
129
|
+
value = argv.shift
|
129
130
|
if process_options && value.start_with?('-')
|
130
131
|
if value.eql?('--')
|
131
|
-
process_options=false
|
132
|
+
process_options = false
|
132
133
|
else
|
133
134
|
@unprocessed_cmd_line_options.push(value)
|
134
135
|
end
|
@@ -137,39 +138,45 @@ module Aspera
|
|
137
138
|
end
|
138
139
|
end
|
139
140
|
end
|
140
|
-
@initial_cli_options
|
141
|
+
@initial_cli_options = @unprocessed_cmd_line_options.dup
|
141
142
|
Log.log.debug("add_cmd_line_options:commands/args=#{@unprocessed_cmd_line_arguments},options=#{@unprocessed_cmd_line_options}".red)
|
142
143
|
end
|
143
144
|
|
144
|
-
def get_next_command(command_list); return get_next_argument('command',command_list); end
|
145
|
+
def get_next_command(command_list); return get_next_argument('command',expected: command_list); end
|
145
146
|
|
146
147
|
# @param expected is
|
147
148
|
# - Array of allowed value (single value)
|
148
149
|
# - :multiple for remaining values
|
149
150
|
# - :single for a single unconstrained value
|
150
|
-
# @param
|
151
|
+
# @param mandatory true/false
|
152
|
+
# @param type expected class for result
|
151
153
|
# @return value, list or nil
|
152
|
-
def get_next_argument(descr,expected
|
153
|
-
|
154
|
+
def get_next_argument(descr,expected: :single,mandatory: true, type: nil)
|
155
|
+
unless type.nil?
|
156
|
+
raise 'internal: type must be a Class' unless type.is_a?(Class)
|
157
|
+
descr="#{descr} (#{type})"
|
158
|
+
end
|
159
|
+
result = nil
|
154
160
|
if !@unprocessed_cmd_line_arguments.empty?
|
155
161
|
# there are values
|
156
162
|
case expected
|
157
163
|
when :single
|
158
|
-
result=ExtendedValue.instance.evaluate(@unprocessed_cmd_line_arguments.shift)
|
164
|
+
result = ExtendedValue.instance.evaluate(@unprocessed_cmd_line_arguments.shift)
|
159
165
|
when :multiple
|
160
166
|
result = @unprocessed_cmd_line_arguments.shift(@unprocessed_cmd_line_arguments.length).map{|v|ExtendedValue.instance.evaluate(v)}
|
161
167
|
# if expecting list and only one arg of type array : it is the list
|
162
168
|
if result.length.eql?(1) && result.first.is_a?(Array)
|
163
|
-
result=result.first
|
169
|
+
result = result.first
|
164
170
|
end
|
165
171
|
else
|
166
|
-
result=self.class.get_from_list(@unprocessed_cmd_line_arguments.shift,descr,expected)
|
172
|
+
result = self.class.get_from_list(@unprocessed_cmd_line_arguments.shift,descr,expected)
|
167
173
|
end
|
168
|
-
elsif
|
174
|
+
elsif mandatory
|
169
175
|
# no value provided
|
170
|
-
result=get_interactive(:argument,descr,expected)
|
176
|
+
result = get_interactive(:argument,descr,expected: expected)
|
171
177
|
end
|
172
178
|
Log.log.debug("#{descr}=#{result}")
|
179
|
+
raise "argument shall be #{type.name}" unless type.nil? || result.is_a?(type)
|
173
180
|
return result
|
174
181
|
end
|
175
182
|
|
@@ -177,19 +184,20 @@ module Aspera
|
|
177
184
|
def declare_option(option_symbol,type)
|
178
185
|
Log.log.debug("declare_option: #{option_symbol}: #{type}: skip=#{@declared_options.has_key?(option_symbol)}".green)
|
179
186
|
if @declared_options.has_key?(option_symbol)
|
180
|
-
raise "INTERNAL ERROR: option #{option_symbol} already declared. only accessor can be redeclared and ignored"
|
187
|
+
raise "INTERNAL ERROR: option #{option_symbol} already declared. only accessor can be redeclared and ignored" \
|
188
|
+
unless @declared_options[option_symbol][:type].eql?(:accessor)
|
181
189
|
return
|
182
190
|
end
|
183
|
-
@declared_options[option_symbol]={type: type}
|
191
|
+
@declared_options[option_symbol] = {type: type}
|
184
192
|
# by default passwords and secrets are sensitive, else specify when declaring the option
|
185
|
-
@declared_options[option_symbol][:sensitive]=true if !%w[password secret key].select{|i| option_symbol.to_s.end_with?(i)}.empty?
|
193
|
+
@declared_options[option_symbol][:sensitive] = true if !%w[password secret key].select{|i| option_symbol.to_s.end_with?(i)}.empty?
|
186
194
|
end
|
187
195
|
|
188
196
|
# define option with handler
|
189
197
|
def set_obj_attr(option_symbol,object,attr_symb,default_value=nil)
|
190
198
|
Log.log.debug("set attr obj #{option_symbol} (#{object},#{attr_symb})")
|
191
199
|
declare_option(option_symbol,:accessor)
|
192
|
-
@declared_options[option_symbol][:accessor]=AttrAccessor.new(object,attr_symb)
|
200
|
+
@declared_options[option_symbol][:accessor] = AttrAccessor.new(object,attr_symb)
|
193
201
|
set_option(option_symbol,default_value,'default obj attr') if !default_value.nil?
|
194
202
|
end
|
195
203
|
|
@@ -200,14 +208,14 @@ module Aspera
|
|
200
208
|
raise 'ERROR: cannot set undeclared option'
|
201
209
|
#declare_option(option_symbol)
|
202
210
|
end
|
203
|
-
value=ExtendedValue.instance.evaluate(value)
|
204
|
-
value=Manager.enum_to_bool(value) if @declared_options[option_symbol][:values].eql?(BOOLEAN_VALUES)
|
211
|
+
value = ExtendedValue.instance.evaluate(value)
|
212
|
+
value = Manager.enum_to_bool(value) if @declared_options[option_symbol][:values].eql?(BOOLEAN_VALUES)
|
205
213
|
Log.log.debug("set #{option_symbol}=#{value} (#{@declared_options[option_symbol][:type]}) : #{where}")
|
206
214
|
case @declared_options[option_symbol][:type]
|
207
215
|
when :accessor
|
208
|
-
@declared_options[option_symbol][:accessor].value=value
|
216
|
+
@declared_options[option_symbol][:accessor].value = value
|
209
217
|
when :value
|
210
|
-
@declared_options[option_symbol][:value]=value
|
218
|
+
@declared_options[option_symbol][:value] = value
|
211
219
|
else # nil or other
|
212
220
|
raise 'error'
|
213
221
|
end
|
@@ -216,33 +224,33 @@ module Aspera
|
|
216
224
|
# get an option value by name
|
217
225
|
# either return value or call handler, can return nil
|
218
226
|
# ask interactively if requested/required
|
219
|
-
def get_option(option_symbol,is_type
|
220
|
-
result=nil
|
227
|
+
def get_option(option_symbol,is_type: :optional)
|
228
|
+
result = nil
|
221
229
|
if @declared_options.has_key?(option_symbol)
|
222
230
|
case @declared_options[option_symbol][:type]
|
223
231
|
when :accessor
|
224
|
-
result
|
232
|
+
result = @declared_options[option_symbol][:accessor].value
|
225
233
|
when :value
|
226
|
-
result
|
234
|
+
result = @declared_options[option_symbol][:value]
|
227
235
|
else
|
228
236
|
raise 'unknown type'
|
229
237
|
end
|
230
238
|
Log.log.debug("get #{option_symbol} (#{@declared_options[option_symbol][:type]}) : #{result}")
|
231
239
|
end
|
232
240
|
# do not fail for manual generation if option mandatory but not set
|
233
|
-
result='' if result.nil? && !@fail_on_missing_mandatory
|
241
|
+
result = '' if result.nil? && !@fail_on_missing_mandatory
|
234
242
|
#Log.log.debug("interactive=#{@ask_missing_mandatory}")
|
235
243
|
if result.nil?
|
236
244
|
if !@ask_missing_mandatory
|
237
245
|
raise CliBadArgument,"Missing mandatory option: #{option_symbol}" if is_type.eql?(:mandatory)
|
238
246
|
elsif @ask_missing_optional || is_type.eql?(:mandatory)
|
239
247
|
# ask_missing_mandatory
|
240
|
-
expected
|
248
|
+
expected = :single
|
241
249
|
#print "please enter: #{option_symbol.to_s}"
|
242
250
|
if @declared_options.has_key?(option_symbol) && @declared_options[option_symbol].has_key?(:values)
|
243
|
-
expected
|
251
|
+
expected = @declared_options[option_symbol][:values]
|
244
252
|
end
|
245
|
-
result=get_interactive(:option,option_symbol.to_s,expected)
|
253
|
+
result = get_interactive(:option,option_symbol.to_s,expected: expected)
|
246
254
|
set_option(option_symbol,result,'interactive')
|
247
255
|
end
|
248
256
|
end
|
@@ -250,7 +258,7 @@ module Aspera
|
|
250
258
|
end
|
251
259
|
|
252
260
|
# param must be hash
|
253
|
-
def add_option_preset(preset_hash,op
|
261
|
+
def add_option_preset(preset_hash,op: :push)
|
254
262
|
Log.log.debug("add_option_preset=#{preset_hash}")
|
255
263
|
raise "internal error: setting default with no hash: #{preset_hash.class}" if !preset_hash.is_a?(Hash)
|
256
264
|
# incremental override
|
@@ -263,11 +271,11 @@ module Aspera
|
|
263
271
|
Log.log.debug("add_opt_list #{option_symbol}")
|
264
272
|
on_args.unshift(symbol_to_option(option_symbol,'ENUM'))
|
265
273
|
# this option value must be a symbol
|
266
|
-
@declared_options[option_symbol][:values]=values
|
267
|
-
value=get_option(option_symbol)
|
268
|
-
help_values=values.map{|i|i.eql?(value)?highlight_current(i):i}.join(', ')
|
274
|
+
@declared_options[option_symbol][:values] = values
|
275
|
+
value = get_option(option_symbol)
|
276
|
+
help_values = values.map{|i|i.eql?(value) ? highlight_current(i) : i}.join(', ')
|
269
277
|
if values.eql?(BOOLEAN_VALUES)
|
270
|
-
help_values=BOOLEAN_SIMPLE.map{|i|(i.eql?(:yes) && value) || (i.eql?(:no) && !value) ? highlight_current(i) : i}.join(', ')
|
278
|
+
help_values = BOOLEAN_SIMPLE.map{|i|(i.eql?(:yes) && value) || (i.eql?(:no) && !value) ? highlight_current(i) : i}.join(', ')
|
271
279
|
end
|
272
280
|
on_args.push(values)
|
273
281
|
on_args.push("#{help}: #{help_values}")
|
@@ -277,6 +285,9 @@ module Aspera
|
|
277
285
|
|
278
286
|
def add_opt_boolean(option_symbol,help,*on_args)
|
279
287
|
add_opt_list(option_symbol,BOOLEAN_VALUES,help,*on_args)
|
288
|
+
# if default was defined for obj, it may still be enum (yes/no) instead of boolean
|
289
|
+
default_value=get_option(option_symbol)
|
290
|
+
set_option(option_symbol,default_value,'opt boolean') unless default_value.nil?
|
280
291
|
end
|
281
292
|
|
282
293
|
# define an option with open values
|
@@ -297,7 +308,7 @@ module Aspera
|
|
297
308
|
@parser.on(*on_args) do |v|
|
298
309
|
case v
|
299
310
|
when 'now' then set_option(option_symbol,Manager.time_to_string(Time.now),'cmdline')
|
300
|
-
when /^-([0-9]+)h/ then set_option(option_symbol,Manager.time_to_string(Time.now-(3600*Regexp.last_match(1).to_i)),'cmdline')
|
311
|
+
when /^-([0-9]+)h/ then set_option(option_symbol,Manager.time_to_string(Time.now - (3600 * Regexp.last_match(1).to_i)),'cmdline')
|
301
312
|
else set_option(option_symbol,v,'cmdline')
|
302
313
|
end
|
303
314
|
end
|
@@ -318,7 +329,7 @@ module Aspera
|
|
318
329
|
|
319
330
|
# unprocessed options or arguments ?
|
320
331
|
def final_errors
|
321
|
-
result=[]
|
332
|
+
result = []
|
322
333
|
result.push("unprocessed options: #{@unprocessed_cmd_line_options}") unless @unprocessed_cmd_line_options.empty?
|
323
334
|
result.push("unprocessed values: #{@unprocessed_cmd_line_arguments}") unless @unprocessed_cmd_line_arguments.empty?
|
324
335
|
return result
|
@@ -326,18 +337,18 @@ module Aspera
|
|
326
337
|
|
327
338
|
# get all original options on command line used to generate a config in config file
|
328
339
|
def get_options_table(remove_from_remaining: true)
|
329
|
-
result={}
|
340
|
+
result = {}
|
330
341
|
@initial_cli_options.each do |optionval|
|
331
342
|
case optionval
|
332
343
|
when /^--([^=]+)$/
|
333
344
|
# ignore
|
334
345
|
when /^--([^=]+)=(.*)$/
|
335
|
-
name=Regexp.last_match(1)
|
336
|
-
value=Regexp.last_match(2)
|
346
|
+
name = Regexp.last_match(1)
|
347
|
+
value = Regexp.last_match(2)
|
337
348
|
name.gsub!(OPTION_SEP_LINE,OPTION_SEP_NAME)
|
338
|
-
value=ExtendedValue.instance.evaluate(value)
|
349
|
+
value = ExtendedValue.instance.evaluate(value)
|
339
350
|
Log.log.debug("option #{name}=#{value}")
|
340
|
-
result[name]=value
|
351
|
+
result[name] = value
|
341
352
|
@unprocessed_cmd_line_options.delete(optionval) if remove_from_remaining
|
342
353
|
else
|
343
354
|
raise CliBadArgument,"wrong option format: #{optionval}"
|
@@ -348,10 +359,10 @@ module Aspera
|
|
348
359
|
|
349
360
|
# return options as taken from config file and command line just before command execution
|
350
361
|
def declared_options(only_defined: false)
|
351
|
-
result={}
|
362
|
+
result = {}
|
352
363
|
@declared_options.keys.each do |option_symb|
|
353
|
-
v=get_option(option_symb)
|
354
|
-
result[option_symb.to_s]=v unless only_defined && v.nil?
|
364
|
+
v = get_option(option_symb)
|
365
|
+
result[option_symb.to_s] = v unless only_defined && v.nil?
|
355
366
|
end
|
356
367
|
return result
|
357
368
|
end
|
@@ -363,7 +374,7 @@ module Aspera
|
|
363
374
|
apply_options_preset(@unprocessed_defaults,'file')
|
364
375
|
apply_options_preset(@unprocessed_env,'env')
|
365
376
|
# command line override
|
366
|
-
unknown_options=[]
|
377
|
+
unknown_options = []
|
367
378
|
begin
|
368
379
|
# remove known options one by one, exception if unknown
|
369
380
|
Log.log.debug('before parse'.red)
|
@@ -377,47 +388,47 @@ module Aspera
|
|
377
388
|
end
|
378
389
|
Log.log.debug("remains: #{unknown_options}")
|
379
390
|
# set unprocessed options for next time
|
380
|
-
@unprocessed_cmd_line_options=unknown_options
|
391
|
+
@unprocessed_cmd_line_options = unknown_options
|
381
392
|
end
|
382
393
|
|
383
394
|
private
|
384
395
|
|
385
396
|
def prompt_user_input(prompt,sensitive)
|
386
397
|
return $stdin.getpass("#{prompt}> ") if sensitive
|
387
|
-
print
|
398
|
+
print("#{prompt}> ")
|
388
399
|
return $stdin.gets.chomp
|
389
400
|
end
|
390
401
|
|
391
|
-
def get_interactive(type,descr,expected
|
402
|
+
def get_interactive(type,descr,expected: :single)
|
392
403
|
if !@ask_missing_mandatory
|
393
404
|
raise CliBadArgument,self.class.bad_arg_message_multi("missing: #{descr}",expected) if expected.is_a?(Array)
|
394
405
|
raise CliBadArgument,"missing argument (#{expected}): #{descr}"
|
395
406
|
end
|
396
|
-
result=nil
|
407
|
+
result = nil
|
397
408
|
sensitive = type.eql?(:option) && @declared_options[descr.to_sym][:sensitive]
|
398
|
-
default_prompt="#{type}: #{descr}"
|
409
|
+
default_prompt = "#{type}: #{descr}"
|
399
410
|
# ask interactively
|
400
411
|
case expected
|
401
412
|
when :multiple
|
402
|
-
result=[]
|
413
|
+
result = []
|
403
414
|
puts(' (one per line, end with empty line)')
|
404
415
|
loop do
|
405
|
-
entry=prompt_user_input(default_prompt,sensitive)
|
416
|
+
entry = prompt_user_input(default_prompt,sensitive)
|
406
417
|
break if entry.empty?
|
407
418
|
result.push(ExtendedValue.instance.evaluate(entry))
|
408
419
|
end
|
409
420
|
when :single
|
410
|
-
result=ExtendedValue.instance.evaluate(prompt_user_input(default_prompt,sensitive))
|
421
|
+
result = ExtendedValue.instance.evaluate(prompt_user_input(default_prompt,sensitive))
|
411
422
|
else # one fixed
|
412
|
-
result=self.class.get_from_list(prompt_user_input("#{expected.join(' ')}\n#{default_prompt}",sensitive),descr,expected)
|
423
|
+
result = self.class.get_from_list(prompt_user_input("#{expected.join(' ')}\n#{default_prompt}",sensitive),descr,expected)
|
413
424
|
end
|
414
425
|
return result
|
415
426
|
end
|
416
427
|
|
417
428
|
# generate command line option from option symbol
|
418
429
|
def symbol_to_option(symbol,opt_val)
|
419
|
-
result='--'+symbol.to_s.gsub(OPTION_SEP_NAME,OPTION_SEP_LINE)
|
420
|
-
result=result+'='+opt_val unless opt_val.nil?
|
430
|
+
result = '--' + symbol.to_s.gsub(OPTION_SEP_NAME,OPTION_SEP_LINE)
|
431
|
+
result = result + '=' + opt_val unless opt_val.nil?
|
421
432
|
return result
|
422
433
|
end
|
423
434
|
|
@@ -426,13 +437,13 @@ module Aspera
|
|
426
437
|
end
|
427
438
|
|
428
439
|
def apply_options_preset(preset,where)
|
429
|
-
unprocessed=[]
|
440
|
+
unprocessed = []
|
430
441
|
preset.each do |pair|
|
431
|
-
k,v
|
442
|
+
k,v = *pair
|
432
443
|
if @declared_options.has_key?(k)
|
433
444
|
# constrained parameters as string are revert to symbol
|
434
445
|
if @declared_options[k].has_key?(:values) && v.is_a?(String)
|
435
|
-
v=self.class.get_from_list(v,k.to_s+" in #{where}",@declared_options[k][:values])
|
446
|
+
v = self.class.get_from_list(v,k.to_s + " in #{where}",@declared_options[k][:values])
|
436
447
|
end
|
437
448
|
set_option(k,v,where)
|
438
449
|
else
|
data/lib/aspera/cli/plugin.rb
CHANGED
@@ -1,69 +1,78 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aspera
|
3
4
|
module Cli
|
4
5
|
# base class for plugins modules
|
5
6
|
class Plugin
|
6
7
|
# operation without id
|
7
|
-
GLOBAL_OPS=[
|
8
|
+
GLOBAL_OPS = %i[create list].freeze
|
8
9
|
# operation on specific instance
|
9
|
-
INSTANCE_OPS=[
|
10
|
-
ALL_OPS=[GLOBAL_OPS,INSTANCE_OPS].flatten.freeze
|
10
|
+
INSTANCE_OPS = %i[modify delete show].freeze
|
11
|
+
ALL_OPS = [GLOBAL_OPS,INSTANCE_OPS].flatten.freeze
|
11
12
|
# max number of items for list command
|
12
|
-
MAX_ITEMS='max'
|
13
|
+
MAX_ITEMS = 'max'
|
13
14
|
# max number of pages for list command
|
14
|
-
MAX_PAGES='pmax'
|
15
|
+
MAX_PAGES = 'pmax'
|
16
|
+
|
17
|
+
#AGENTS=%i[options transfer config formater persistency].freeze
|
15
18
|
|
16
19
|
# global for inherited classes
|
17
|
-
@@options_created=false # rubocop:disable Style/ClassVars
|
20
|
+
@@options_created = false # rubocop:disable Style/ClassVars
|
18
21
|
|
19
22
|
def initialize(env)
|
20
|
-
|
21
|
-
raise
|
23
|
+
raise 'must be Hash' unless env.is_a?(Hash)
|
24
|
+
#env.each_key {|k| raise "wrong agent key #{k}" unless AGENTS.include?(k)}
|
25
|
+
@agents = env
|
26
|
+
# check presence in descendant of mandatory method and constant
|
27
|
+
raise StandardError,"missing method 'execute_action' in #{self.class}" unless respond_to?(:execute_action)
|
22
28
|
raise StandardError,'ACTIONS shall be redefined by subclass' unless self.class.constants.include?(:ACTIONS)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
options.parser.separator 'OPTIONS:'
|
28
|
-
end
|
29
|
+
options.parser.separator('')
|
30
|
+
options.parser.separator("COMMAND: #{self.class.name.split('::').last.downcase}")
|
31
|
+
options.parser.separator("SUBCOMMANDS: #{self.class.const_get(:ACTIONS).map(&:to_s).join(' ')}")
|
32
|
+
options.parser.separator('OPTIONS:')
|
29
33
|
return if @@options_created
|
30
34
|
options.add_opt_simple(:value,'extended value for create, update, list filter')
|
31
35
|
options.add_opt_simple(:property,'name of property to set')
|
32
36
|
options.add_opt_simple(:id,"resource identifier (#{INSTANCE_OPS.join(',')})")
|
33
37
|
options.parse_options!
|
34
|
-
@@options_created=true # rubocop:disable Style/ClassVars
|
38
|
+
@@options_created = true # rubocop:disable Style/ClassVars
|
35
39
|
end
|
36
40
|
|
37
41
|
# must be called AFTER the instance action
|
38
42
|
def instance_identifier
|
39
|
-
res_id=options.get_option(:id)
|
40
|
-
res_id=options.get_next_argument('identifier') if res_id.nil?
|
43
|
+
res_id = options.get_option(:id)
|
44
|
+
res_id = options.get_next_argument('identifier') if res_id.nil?
|
41
45
|
return res_id
|
42
46
|
end
|
43
47
|
|
48
|
+
# TODO
|
49
|
+
def get_next_id_command(instance_ops: INSTANCE_OPS,global_ops: GLOBAL_OPS)
|
50
|
+
return get_next_argument('command',expected: command_list)
|
51
|
+
end
|
52
|
+
|
44
53
|
# @param command [Symbol] command to execute: create show list modify delete
|
45
54
|
# @param rest_api [Rest] api to use
|
46
55
|
# @param res_class_path [String] sub path in URL to resource relative to base url
|
47
56
|
# @param display_fields [Array] fields to display by default
|
48
57
|
# @param id_default [String] default identifier to use for existing entity commands (show, modify)
|
49
|
-
# @param
|
50
|
-
def entity_command(command,rest_api,res_class_path,display_fields: nil,id_default: nil,
|
58
|
+
# @param item_list_key [String] result is in a subkey of the json
|
59
|
+
def entity_command(command,rest_api,res_class_path,display_fields: nil,id_default: nil,item_list_key: false)
|
51
60
|
if INSTANCE_OPS.include?(command)
|
52
61
|
begin
|
53
|
-
one_res_id=instance_identifier
|
62
|
+
one_res_id = instance_identifier
|
54
63
|
rescue StandardError => e
|
55
64
|
raise e if id_default.nil?
|
56
|
-
one_res_id=id_default
|
65
|
+
one_res_id = id_default
|
57
66
|
end
|
58
|
-
one_res_path="#{res_class_path}/#{one_res_id}"
|
67
|
+
one_res_path = "#{res_class_path}/#{one_res_id}"
|
59
68
|
end
|
60
69
|
# parameters mandatory for create/modify
|
61
|
-
if [
|
62
|
-
parameters=options.get_option(:value
|
70
|
+
if %i[create modify].include?(command)
|
71
|
+
parameters = options.get_option(:value,is_type: :mandatory)
|
63
72
|
end
|
64
73
|
# parameters optional for list
|
65
74
|
if [:list].include?(command)
|
66
|
-
parameters=options.get_option(:value
|
75
|
+
parameters = options.get_option(:value)
|
67
76
|
end
|
68
77
|
case command
|
69
78
|
when :create
|
@@ -71,17 +80,26 @@ module Aspera
|
|
71
80
|
when :show
|
72
81
|
return {type: :single_object, data: rest_api.read(one_res_path)[:data], fields: display_fields}
|
73
82
|
when :list
|
74
|
-
resp=rest_api.read(res_class_path,parameters)
|
75
|
-
data=resp[:data]
|
83
|
+
resp = rest_api.read(res_class_path,parameters)
|
84
|
+
data = resp[:data]
|
76
85
|
# TODO: not generic : which application is this for ?
|
77
86
|
if resp[:http]['Content-Type'].start_with?('application/vnd.api+json')
|
78
|
-
data=data[res_class_path]
|
87
|
+
data = data[res_class_path]
|
88
|
+
end
|
89
|
+
if item_list_key
|
90
|
+
item_list=data[item_list_key]
|
91
|
+
total_count=data['total_count']
|
92
|
+
if !total_count.nil?
|
93
|
+
count_msg = "Items: #{item_list.length}/#{total_count}"
|
94
|
+
count_msg = count_msg.bg_red unless item_list.length.eql?(total_count.to_i)
|
95
|
+
self.format.display_status(count_msg)
|
96
|
+
end
|
97
|
+
data = item_list
|
79
98
|
end
|
80
|
-
data=data[res_class_path] if use_subkey
|
81
99
|
return {type: :object_list, data: data, fields: display_fields}
|
82
100
|
when :modify
|
83
|
-
property=options.get_option(:property
|
84
|
-
parameters={property => parameters} unless property.nil?
|
101
|
+
property = options.get_option(:property)
|
102
|
+
parameters = {property => parameters} unless property.nil?
|
85
103
|
rest_api.update(one_res_path,parameters)
|
86
104
|
return Main.result_status('modified')
|
87
105
|
when :delete
|
@@ -95,7 +113,7 @@ module Aspera
|
|
95
113
|
# implement generic rest operations on given resource path
|
96
114
|
def entity_action(rest_api,res_class_path,**opts)
|
97
115
|
#res_name=res_class_path.gsub(%r{^.*/},'').gsub(%r{s$},'').gsub('_',' ')
|
98
|
-
command=options.get_next_command(ALL_OPS)
|
116
|
+
command = options.get_next_command(ALL_OPS)
|
99
117
|
return entity_command(command,rest_api,res_class_path,**opts)
|
100
118
|
end
|
101
119
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'aspera/rest'
|
3
4
|
require 'aspera/aoc'
|
4
5
|
|
@@ -6,15 +7,15 @@ module Aspera
|
|
6
7
|
module Cli
|
7
8
|
module Plugins
|
8
9
|
class Alee < BasicAuthPlugin
|
9
|
-
ACTIONS=[
|
10
|
+
ACTIONS = %i[entitlement].freeze
|
10
11
|
|
11
12
|
def execute_action
|
12
|
-
command=options.get_next_command(ACTIONS)
|
13
|
+
command = options.get_next_command(ACTIONS)
|
13
14
|
case command
|
14
15
|
when :entitlement
|
15
|
-
entitlement_id = options.get_option(:username
|
16
|
-
customer_id = options.get_option(:password
|
17
|
-
api_metering=AoC.metering_api(entitlement_id,customer_id)
|
16
|
+
entitlement_id = options.get_option(:username,is_type: :mandatory)
|
17
|
+
customer_id = options.get_option(:password,is_type: :mandatory)
|
18
|
+
api_metering = AoC.metering_api(entitlement_id,customer_id)
|
18
19
|
return {type: :single_object, data: api_metering.read('entitlement')[:data]}
|
19
20
|
end
|
20
21
|
end
|