aspera-cli 4.26.1 → 4.26.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +19 -1
  4. data/CONTRIBUTING.md +2 -5
  5. data/bin/ascli +2 -2
  6. data/lib/aspera/agent/direct.rb +1 -1
  7. data/lib/aspera/agent/factory.rb +4 -0
  8. data/lib/aspera/agent/httpgw.rb +1 -1
  9. data/lib/aspera/agent/node.rb +2 -2
  10. data/lib/aspera/api/aoc.rb +43 -36
  11. data/lib/aspera/api/cos_node.rb +1 -1
  12. data/lib/aspera/api/faspex.rb +7 -6
  13. data/lib/aspera/api/node.rb +7 -7
  14. data/lib/aspera/ascmd.rb +4 -4
  15. data/lib/aspera/ascp/installation.rb +6 -2
  16. data/lib/aspera/cli/context.rb +58 -0
  17. data/lib/aspera/cli/extended_value.rb +3 -2
  18. data/lib/aspera/cli/formatter.rb +83 -184
  19. data/lib/aspera/cli/http.rb +167 -0
  20. data/lib/aspera/cli/manager.rb +3 -2
  21. data/lib/aspera/cli/plugins/alee.rb +2 -2
  22. data/lib/aspera/cli/plugins/aoc.rb +78 -67
  23. data/lib/aspera/cli/plugins/ats.rb +16 -16
  24. data/lib/aspera/cli/plugins/base.rb +18 -12
  25. data/lib/aspera/cli/plugins/config.rb +166 -438
  26. data/lib/aspera/cli/plugins/console.rb +7 -7
  27. data/lib/aspera/cli/plugins/cos.rb +2 -2
  28. data/lib/aspera/cli/plugins/factory.rb +3 -0
  29. data/lib/aspera/cli/plugins/faspex.rb +21 -21
  30. data/lib/aspera/cli/plugins/faspex5.rb +64 -44
  31. data/lib/aspera/cli/plugins/faspio.rb +1 -1
  32. data/lib/aspera/cli/plugins/httpgw.rb +2 -2
  33. data/lib/aspera/cli/plugins/node.rb +79 -79
  34. data/lib/aspera/cli/plugins/orchestrator.rb +21 -26
  35. data/lib/aspera/cli/plugins/preview.rb +9 -9
  36. data/lib/aspera/cli/plugins/server.rb +7 -7
  37. data/lib/aspera/cli/plugins/shares.rb +2 -2
  38. data/lib/aspera/cli/preset_manager.rb +235 -0
  39. data/lib/aspera/cli/result.rb +310 -0
  40. data/lib/aspera/cli/{main.rb → runner.rb} +14 -155
  41. data/lib/aspera/cli/sync_actions.rb +14 -10
  42. data/lib/aspera/cli/terminal_formatter.rb +65 -0
  43. data/lib/aspera/cli/transfer_progress.rb +6 -6
  44. data/lib/aspera/cli/version.rb +1 -1
  45. data/lib/aspera/cli/wizard.rb +5 -6
  46. data/lib/aspera/command_line_builder.rb +1 -1
  47. data/lib/aspera/data_repository.rb +4 -0
  48. data/lib/aspera/dot_container.rb +1 -1
  49. data/lib/aspera/environment.rb +22 -3
  50. data/lib/aspera/faspex_gw.rb +1 -1
  51. data/lib/aspera/json_rpc.rb +6 -5
  52. data/lib/aspera/keychain/base.rb +1 -1
  53. data/lib/aspera/keychain/encrypted_hash.rb +1 -1
  54. data/lib/aspera/keychain/factory.rb +1 -1
  55. data/lib/aspera/keychain/macos_security.rb +1 -1
  56. data/lib/aspera/log.rb +6 -2
  57. data/lib/aspera/nagios.rb +2 -2
  58. data/lib/aspera/oauth/base.rb +5 -5
  59. data/lib/aspera/oauth/boot.rb +43 -0
  60. data/lib/aspera/oauth/factory.rb +37 -13
  61. data/lib/aspera/oauth/web.rb +2 -2
  62. data/lib/aspera/oauth.rb +1 -0
  63. data/lib/aspera/persistency_action_once.rb +2 -2
  64. data/lib/aspera/preview/file_types.rb +4 -0
  65. data/lib/aspera/products/connect.rb +3 -0
  66. data/lib/aspera/products/transferd.rb +2 -2
  67. data/lib/aspera/proxy_auto_config.rb +3 -3
  68. data/lib/aspera/rest.rb +8 -4
  69. data/lib/aspera/rest_error_analyzer.rb +4 -0
  70. data/lib/aspera/rest_list.rb +10 -3
  71. data/lib/aspera/schema/IBM Aspera Faspex API-5.0-enhanced.yaml +14 -4
  72. data/lib/aspera/schema/IBM Aspera on Cloud API-0.2.6-enhanced.yaml +827 -88
  73. data/lib/aspera/schema/async_tables.yaml +361 -0
  74. data/lib/aspera/schema/reader.rb +1 -1
  75. data/lib/aspera/schema/registry.rb +13 -6
  76. data/lib/aspera/secret_hider.rb +4 -0
  77. data/lib/aspera/sync/database.rb +14 -10
  78. data/lib/aspera/sync/operations.rb +5 -5
  79. data/lib/aspera/temp_file_manager.rb +4 -0
  80. data/lib/aspera/transfer/parameters.rb +4 -4
  81. data/lib/aspera/transfer/resumer.rb +1 -1
  82. data/lib/aspera/transfer/spec.schema.yaml +17 -8
  83. data/lib/aspera/transfer/uri.rb +1 -1
  84. data.tar.gz.sig +0 -0
  85. metadata +21 -14
  86. metadata.gz.sig +0 -0
@@ -2,6 +2,7 @@
2
2
 
3
3
  # cspell:ignore jsonpp
4
4
  require 'aspera/cli/special_values'
5
+ require 'aspera/cli/terminal_formatter'
5
6
  require 'aspera/preview/terminal'
6
7
  require 'aspera/secret_hider'
7
8
  require 'aspera/environment'
@@ -9,7 +10,6 @@ require 'aspera/log'
9
10
  require 'aspera/assert'
10
11
  require 'aspera/markdown'
11
12
  require 'aspera/dot_container'
12
- require 'aspera/formatter_interface'
13
13
  require 'terminal-table'
14
14
  require 'tty-spinner'
15
15
  require 'yaml'
@@ -19,75 +19,8 @@ require 'word_wrap'
19
19
 
20
20
  module Aspera
21
21
  module Cli
22
- # Terminal formatter with ANSI colors and Unicode support
23
- # @see FormatterInterface
24
- # @see MarkdownFormatter (in build/lib/doc_helper.rb)
25
- module TerminalFormatter
26
- include FormatterInterface
27
-
28
- # Format boolean with colored symbol (✓/✗ or Y/ )
29
- def tick(yes)
30
- result =
31
- if Environment.terminal_supports_unicode?
32
- yes ? "\u2713" : "\u2717"
33
- else
34
- yes ? 'Y' : ' '
35
- end
36
- return result.green if yes
37
- return result.red
38
- end
39
-
40
- # Format special values with colors (dim for empty, reverse for others)
41
- def special_format(what)
42
- result = "<#{what}>"
43
- return %w[null empty].any?{ |s| what.include?(s)} ? result.dim : result.reverse_color
44
- end
45
-
46
- # Prepare table row for terminal display (word wrap arrays)
47
- def check_row(row)
48
- row.each_key do |k|
49
- row[k] = row[k].map{ |i| WordWrap.ww(i.to_s, 120).chomp}.join("\n") if row[k].is_a?(Array)
50
- end
51
- end
52
-
53
- # Convert Markdown to terminal format (**bold** -> blue, `code` -> bold)
54
- # @param match [MatchData, String]
55
- def markdown_text(match)
56
- if match.is_a?(String)
57
- match = Markdown::FORMATS.match(match)
58
- Aspera.assert(match)
59
- end
60
- Aspera.assert_type(match, MatchData)
61
- if match[:entity]
62
- Aspera.assert_values(match[:entity], %w[bsol])
63
- '\\'
64
- elsif match[:bold]
65
- match[:bold].to_s.blue
66
- elsif match[:code]
67
- match[:code].to_s.bold
68
- else
69
- Aspera.error_unexpected_value(match.to_s)
70
- end
71
- end
72
-
73
- module_function :tick, :special_format, :check_row, :markdown_text
74
- end
75
-
76
22
  # Take care of CLI output on terminal
77
23
  class Formatter
78
- # remove a fields from the list
79
- FIELDS_LESS = '-'
80
- # supported output formats
81
- DISPLAY_FORMATS = %i[text nagios ruby json jsonpp yaml table csv image].freeze
82
- # user output levels
83
- DISPLAY_LEVELS = %i[info data error].freeze
84
- # column names for single object display in table
85
- SINGLE_OBJECT_COLUMN_NAMES = %i[field value].freeze
86
- # Terminal: vertical separator for list of strings.
87
- STR_LST_SEP_VERT = "\n"
88
-
89
- private_constant :FIELDS_LESS, :DISPLAY_FORMATS, :DISPLAY_LEVELS, :SINGLE_OBJECT_COLUMN_NAMES, :STR_LST_SEP_VERT
90
-
91
24
  class << self
92
25
  # Replace special values with a readable version on terminal
93
26
  def replace_specific_for_terminal(input_hash, string_list_separator)
@@ -134,6 +67,17 @@ module Aspera
134
67
  @spinner = nil
135
68
  end
136
69
 
70
+ # Display item count if total is provided
71
+ def display_item_count(count, total)
72
+ return if total.nil?
73
+ count = count.to_i
74
+ total = total.to_i
75
+ return if total.eql?(0) && count.eql?(0)
76
+ count_msg = "Items: #{count}/#{total}"
77
+ count_msg = count_msg.bg_red unless count.eql?(total)
78
+ display_status(count_msg)
79
+ end
80
+
137
81
  def long_operation(title = nil, action: :spin)
138
82
  return unless Environment.terminal?
139
83
  return if %i[error data].include?(@options[:display])
@@ -214,10 +158,16 @@ module Aspera
214
158
  nil
215
159
  end
216
160
 
217
- # Main output method
218
- # data: for requested data, not displayed if level==error
219
- # info: additional info, displayed if level==info
220
- # error: always displayed on stderr
161
+ # Main output method for displaying messages to the user
162
+ # This method is used by Result classes to output formatted data
163
+ # @param message_level [Symbol] The level of the message - must be one of: :data, :info, :error
164
+ # @param message [String] The message to display
165
+ # @param hide_secrets [Boolean] Whether to hide secrets in the message (default: true)
166
+ # @return [void]
167
+ # @note Message display behavior depends on the message_level:
168
+ # - +:data+ messages are displayed unless display level is +:error+
169
+ # - +:info+ messages are only displayed when display level is +:info+
170
+ # - +:error+ messages are always displayed on stderr
221
171
  def display_message(message_level, message, hide_secrets: true)
222
172
  message = SecretHider.instance.hide_secrets_in_string(message) if hide_secrets && message.is_a?(String) && hide_secrets?
223
173
  case message_level
@@ -232,15 +182,7 @@ module Aspera
232
182
  display_message(:info, status, **kwargs)
233
183
  end
234
184
 
235
- def display_item_count(number, total)
236
- number = number.to_i
237
- total = total.to_i
238
- return if total.eql?(0) && number.eql?(0)
239
- count_msg = "Items: #{number}/#{total}"
240
- count_msg = count_msg.bg_red unless number.eql?(total)
241
- display_status(count_msg)
242
- end
243
-
185
+ # Check if secrets should be hidden
244
186
  def hide_secrets?
245
187
  !@options[:show_secrets] && !@options[:display].eql?(:data)
246
188
  end
@@ -250,111 +192,55 @@ module Aspera
250
192
  SecretHider.instance.deep_remove_secret(data) if hide_secrets?
251
193
  end
252
194
 
253
- # Display results, especially the table format
254
- # @param type [Symbol] Type of data
255
- # @param data [Object] Data to display
256
- # @param fields [Array<String>] List of fields to display
257
- # @param total [Integer] Total number of items
258
- # @param name [String] Name of the column to display
259
- def display_results(type:, data: nil, fields: nil, total: nil, name: nil)
260
- Log.log.debug{"display_results: type=#{type}"}
261
- Log.dump(:data, data, level: :trace1)
262
- Log.dump(:fields, fields, level: :trace1)
263
- Aspera.assert_type(type, Symbol){'result must have type'}
264
- Aspera.assert(!data.nil? || %i[empty nothing].include?(type)){'result must have data'}
265
- display_item_count(data.length, total) unless total.nil?
266
- hide_secrets(data)
267
- data = SecretHider.instance.hide_secrets_in_string(data) if data.is_a?(String) && hide_secrets?
268
- @options[:format] = :image if type.eql?(:image)
269
- case @options[:format]
270
- when :text
271
- display_message(:data, data.to_s)
272
- when :nagios
273
- Nagios.process(data)
274
- when :ruby
275
- display_message(:data, PP.pp(filter_list_on_fields(data), +''))
276
- when :json
277
- display_message(:data, JSON.generate(filter_list_on_fields(data)))
278
- when :jsonpp
279
- display_message(:data, JSON.pretty_generate(filter_list_on_fields(data)))
280
- when :yaml
281
- display_message(:data, YAML.dump(filter_list_on_fields(data)))
282
- when :image
283
- # if object or list, then must be a single
284
- case type
285
- when :single_object, :object_list
286
- data = [data] if type.eql?(:single_object)
287
- raise BadArgument, 'image display requires a single result' unless data.length == 1
288
- fields = compute_fields(data, fields)
289
- raise BadArgument, 'select a single field to display' unless fields.length == 1
290
- data = data.first
291
- raise BadArgument, 'no such field' unless data.key?(fields.first)
292
- data = data[fields.first]
293
- end
294
- Aspera.assert_type(data, String){'URL or blob for image'}
295
- # Check if URL
296
- data =
297
- begin
298
- # just validate
299
- URI.parse(data)
300
- if Environment.instance.url_method.eql?(:text)
301
- UriReader.read(data)
302
- else
303
- Environment.instance.open_uri(data)
304
- display_message(:info, "Opened URL in browser: #{data}")
305
- :done
306
- end
307
- rescue URI::InvalidURIError
308
- data
309
- end
310
- # try base64
311
- data = begin
312
- Base64.strict_decode64(data)
313
- rescue
314
- data
315
- end
316
- # here, data is the image blob
317
- display_message(:data, Preview::Terminal.build(data, **@options[:image].symbolize_keys)) unless data.eql?(:done)
318
- when :table, :csv
319
- case type
320
- when :single_object
321
- # :single_object is a Hash, where key=column name
322
- Aspera.assert_type(data, Hash){'result'}
323
- if data.empty?
324
- display_message(:data, TerminalFormatter.special_format('empty dict'))
325
- else
326
- data = DotContainer.new(data).to_dotted if @options[:flat_hash]
327
- display_table([data], compute_fields([data], fields), single: true)
328
- end
329
- when :object_list
330
- # :object_list is an Array of Hash, where key=column name
331
- Aspera.assert_array_all(data, Hash){'result'}
332
- data = data.map{ |obj| DotContainer.new(obj).to_dotted} if @options[:flat_hash]
333
- display_table(data, compute_fields(data, fields), single: type.eql?(:single_object))
334
- when :value_list
335
- # :value_list is a simple array of values, name of column provided in `name`
336
- display_table(data.map{ |i| {name => i}}, [name])
337
- when :special # no table
338
- if data.eql?(:nothing)
339
- Log.log.debug('no result expected')
340
- return
341
- end
342
- display_message(:info, TerminalFormatter.special_format(data.to_s))
343
- return
344
- when :status # no table
345
- # :status displays a simple message
346
- display_message(:info, data)
347
- when :text # no table
348
- # :status displays a simple message
349
- display_message(:data, data)
350
- else Aspera.error_unexpected_value(type){'data type'}
351
- end
352
- else Aspera.error_unexpected_value(@options[:format]){'format'}
353
- end
195
+ # Display results using the Visitor pattern
196
+ # Each Result subclass knows how to format itself by calling the appropriate
197
+ # formatter method, eliminating the need for type checking in the formatter.
198
+ # @param result [Result] Result object to display
199
+ def display_results(result)
200
+ require 'aspera/cli/result'
201
+ Aspera.assert_type(result, Cli::Result){'result must be a Result object'}
202
+
203
+ Log.log.debug{"display_results: result class=#{result.class.name}"}
204
+ Log.dump(:data, result.data, level: :trace1)
205
+ Log.dump(:fields, result.fields, level: :trace1)
206
+
207
+ # Hide secrets in data
208
+ hide_secrets(result.data)
209
+
210
+ # Use the Visitor pattern: delegate formatting to the result object
211
+ result.format(self)
212
+ end
213
+ # Public methods exposed to Result classes for formatting
214
+
215
+ # Get the current format type
216
+ def format_type
217
+ @options[:format]
218
+ end
219
+
220
+ # Set the format type (used by Image result)
221
+ def set_format_type(format)
222
+ @options[:format] = format
223
+ end
224
+
225
+ # Hide secrets in a string
226
+ def hide_secrets_in_string(string)
227
+ SecretHider.instance.hide_secrets_in_string(string)
228
+ end
229
+
230
+ # Get special format string
231
+ def special_format(text)
232
+ TerminalFormatter.special_format(text)
233
+ end
234
+
235
+ # Check if flat_hash option is enabled
236
+ def flat_hash?
237
+ @options[:flat_hash]
354
238
  end
355
- #==========================================================================================
356
239
 
357
- private
240
+ # Get image options
241
+ def image_options
242
+ @options[:image].symbolize_keys
243
+ end
358
244
 
359
245
  # @return all fields of all objects in list of objects
360
246
  def all_fields(data)
@@ -506,6 +392,19 @@ module Aspera
506
392
  end
507
393
  nil
508
394
  end
395
+
396
+ # remove a fields from the list
397
+ FIELDS_LESS = '-'
398
+ # supported output formats
399
+ DISPLAY_FORMATS = %i[text nagios ruby json jsonpp yaml table csv image].freeze
400
+ # user output levels
401
+ DISPLAY_LEVELS = %i[info data error].freeze
402
+ # column names for single object display in table
403
+ SINGLE_OBJECT_COLUMN_NAMES = %i[field value].freeze
404
+ # Terminal: vertical separator for list of strings.
405
+ STR_LST_SEP_VERT = "\n"
406
+
407
+ private_constant :FIELDS_LESS, :DISPLAY_FORMATS, :DISPLAY_LEVELS, :SINGLE_OBJECT_COLUMN_NAMES, :STR_LST_SEP_VERT
509
408
  end
510
409
  end
511
410
  end
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aspera/cli/special_values'
4
+ require 'aspera/log'
5
+ require 'aspera/assert'
6
+ require 'aspera/line_logger'
7
+ require 'openssl'
8
+
9
+ module Aspera
10
+ module Cli
11
+ # Encapsulates all HTTP/S and TLS runtime configuration options.
12
+ # Extracted from Plugins::Config so it can be referenced independently
13
+ # via Context#http_config without coupling to the plugin machinery.
14
+ class Http
15
+ # Certificate file extensions recognized when scanning a folder
16
+ CERT_EXT = %w[crt cer pem der].freeze
17
+ # OpenSSL constant that disables peer verification (VERIFY_NONE)
18
+ SELF_SIGNED_CERT = OpenSSL::SSL.const_get(:enon_yfirev.to_s.upcase.reverse) # cspell: disable-line
19
+
20
+ private_constant :CERT_EXT, :SELF_SIGNED_CERT
21
+
22
+ def initialize
23
+ @insecure = false
24
+ @warn_insecure = true
25
+ @ignore_cert_host_port = []
26
+ @http_options = {}
27
+ @ssl_warned_urls = []
28
+ @certificate_store = nil
29
+ @certificate_paths = nil
30
+ end
31
+
32
+ attr_accessor :insecure, :warn_insecure, :http_options
33
+ attr_reader :ignore_cert_host_port
34
+
35
+ # Declare all HTTP/S CLI options, with handlers pointing to self.
36
+ # Called once from Config#initialize after this object is instantiated.
37
+ # @param options [Aspera::Cli::Manager]
38
+ def declare_options(options)
39
+ options.declare(:insecure, 'HTTP/S: Do not validate any certificate', allowed: Allowed::TYPES_BOOLEAN, handler: {o: self, m: :insecure}, default: false)
40
+ options.declare(:ignore_certificate, 'HTTP/S: Do not validate certificate for these URLs', allowed: [Array, NilClass], handler: {o: self, m: :ignore_cert_host_port})
41
+ options.declare(:warn_insecure, 'HTTP/S: Issue a warning if certificate is ignored', allowed: Allowed::TYPES_BOOLEAN, handler: {o: self, m: :warn_insecure}, default: true)
42
+ options.declare(:cert_stores, 'HTTP/S: List of folder with trusted certificates', allowed: Allowed::TYPES_STRING_ARRAY, handler: {o: self, m: :trusted_cert_locations})
43
+ options.declare(:http_options, 'HTTP/S: Options for HTTP/S socket', allowed: Hash, handler: {o: self, m: :http_options}, default: {})
44
+ options.declare(:http_proxy, 'HTTP/S: URL for proxy with optional credentials', handler: {o: self, m: :http_proxy})
45
+ end
46
+
47
+ # ------------------------------------------------------------------
48
+ # Proxy
49
+ # ------------------------------------------------------------------
50
+
51
+ def http_proxy
52
+ ENV['http_proxy']
53
+ end
54
+
55
+ def http_proxy=(value)
56
+ URI.parse(value)
57
+ ENV['http_proxy'] = value
58
+ end
59
+
60
+ # ------------------------------------------------------------------
61
+ # Per-URL certificate ignore list
62
+ # ------------------------------------------------------------------
63
+
64
+ def ignore_cert_host_port=(url_list)
65
+ url_list.each do |url|
66
+ uri = URI.parse(url)
67
+ raise "Expecting https scheme: #{url}" unless uri.scheme.eql?('https')
68
+ @ignore_cert_host_port.push([uri.host, uri.port].freeze)
69
+ end
70
+ end
71
+
72
+ # Should the certificate be ignored for this host/port?
73
+ # Also logs a warning the first time (if warn_insecure is set).
74
+ def ignore_cert?(address, port)
75
+ endpoint = [address, port].freeze
76
+ ignore_cert = @insecure || @ignore_cert_host_port.any?(endpoint)
77
+ if ignore_cert && @warn_insecure
78
+ base_url = "https://#{address}:#{port}"
79
+ unless @ssl_warned_urls.include?(base_url)
80
+ Log.log.warn{"Ignoring certificate for: #{base_url}. Do not deactivate certificate verification in production."}
81
+ @ssl_warned_urls.push(base_url)
82
+ end
83
+ end
84
+ Log.log.debug{"ignore cert? #{endpoint} -> #{ignore_cert}"}
85
+ ignore_cert
86
+ end
87
+
88
+ # ------------------------------------------------------------------
89
+ # Trusted certificate store / paths
90
+ # ------------------------------------------------------------------
91
+
92
+ # Add files, folders or the default OS locations to the cert store.
93
+ # @param path_list [Array<String>]
94
+ def trusted_cert_locations=(path_list)
95
+ Aspera.assert_type(path_list, Array){'cert locations'}
96
+ if @certificate_store.nil?
97
+ Log.log.debug('Creating SSL Cert store')
98
+ @certificate_store = OpenSSL::X509::Store.new
99
+ @certificate_paths = []
100
+ end
101
+ path_list.each do |path|
102
+ Aspera.assert_type(path, String){'Expecting a String for certificate location'}
103
+ paths_to_add = [path]
104
+ Log.log.debug{"Adding cert location: #{path}"}
105
+ if path.eql?(SpecialValues::DEF)
106
+ @certificate_store.set_default_paths
107
+ paths_to_add = [OpenSSL::X509::DEFAULT_CERT_DIR]
108
+ paths_to_add.push(OpenSSL::X509::DEFAULT_CERT_FILE) unless defined?(JRUBY_VERSION)
109
+ paths_to_add.select!{ |f| File.exist?(f)}
110
+ elsif File.file?(path)
111
+ @certificate_store.add_file(path)
112
+ elsif File.directory?(path)
113
+ @certificate_store.add_path(path)
114
+ else
115
+ raise "No such file or folder: #{path}"
116
+ end
117
+ paths_to_add.each do |p|
118
+ pp = [File.realpath(p)]
119
+ if File.directory?(p)
120
+ pp = Dir.entries(p)
121
+ .map{ |e| File.realpath(File.join(p, e))}
122
+ .select{ |entry| File.file?(entry)}
123
+ .select{ |entry| CERT_EXT.any?{ |ext| entry.end_with?(ext)}}
124
+ end
125
+ @certificate_paths.concat(pp)
126
+ end
127
+ end
128
+ @certificate_paths.uniq!
129
+ end
130
+
131
+ # Return cert file paths (computes OS defaults lazily if never set).
132
+ def trusted_cert_locations
133
+ if @certificate_paths.nil?
134
+ self.trusted_cert_locations = [SpecialValues::DEF]
135
+ locations = @certificate_paths
136
+ # Restore to "lazy" state so next call recomputes if store was reset
137
+ @certificate_paths = @certificate_store = nil
138
+ return locations
139
+ end
140
+ @certificate_paths
141
+ end
142
+
143
+ # ------------------------------------------------------------------
144
+ # HTTP session callback
145
+ # Called every time a new Net::HTTP session is opened.
146
+ # ------------------------------------------------------------------
147
+
148
+ # @param http_session [Net::HTTP]
149
+ def update_session(http_session)
150
+ http_session.set_debug_output(LineLogger.new(:trace2)) if Log.instance.logger.trace2?
151
+ if http_session.use_ssl? && ignore_cert?(http_session.address, http_session.port)
152
+ http_session.verify_mode = SELF_SIGNED_CERT
153
+ end
154
+ http_session.cert_store = @certificate_store if @certificate_store
155
+ Log.log.debug{"Using cert store #{http_session.cert_store} (#{@certificate_store})"} unless http_session.cert_store.nil?
156
+ @http_options.each do |k, v|
157
+ method = "#{k}=".to_sym
158
+ if http_session.respond_to?(method)
159
+ http_session.send(method, v)
160
+ else
161
+ Log.log.error{"Unknown HTTP session attribute: #{k}"}
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'aspera/cli/extended_value'
4
4
  require 'aspera/cli/error'
5
+ require 'aspera/cli/terminal_formatter'
5
6
  require 'aspera/colors'
6
7
  require 'aspera/secret_hider'
7
8
  require 'aspera/log'
@@ -325,7 +326,7 @@ module Aspera
325
326
  Aspera.assert(description[0] == description[0].upcase){"#{option_symbol} description does not start with an uppercase"}
326
327
  Aspera.assert(!['hash', 'extended value'].any?{ |s| description.downcase.include?(s)}){"#{option_symbol} shall use :allowed instead of hash/extended value in option description"}
327
328
  Aspera.assert_type(handler, Hash) if handler
328
- Aspera.assert(handler.keys.sort.eql?(%i[m o])) if handler
329
+ Aspera.assert(handler.keys.sort.eql?(%i[m o]), 'handler must have keys :m and :o') if handler
329
330
  option_attrs = @declared_options[option_symbol] = OptionValue.new(
330
331
  option: option_symbol,
331
332
  description: description,
@@ -647,7 +648,7 @@ module Aspera
647
648
  if !@ask_missing_mandatory
648
649
  message = "Missing #{default_prompt}"
649
650
  message = self.class.multi_choice_assert_msg(message, accept_list) if accept_list
650
- message += "\nGive `#{HELP}` as argument to retrieve the schema of the missing argument." if schema
651
+ message += "\n#{TerminalFormatter::HINT}Give `#{HELP}` as argument to retrieve the schema of the missing argument." if schema
651
652
  raise Cli::MissingArgument, message
652
653
  end
653
654
  # ask interactively
@@ -23,12 +23,12 @@ module Aspera
23
23
  rescue StandardError => e
24
24
  nagios.add_critical('api', e.to_s)
25
25
  end
26
- Main.result_object_list(nagios.status_list)
26
+ Result::ObjectList.new(nagios.status_list)
27
27
  when :entitlement
28
28
  entitlement_id = options.get_option(:username, mandatory: true)
29
29
  customer_id = options.get_option(:password, mandatory: true)
30
30
  api_metering = Api::Alee.new(entitlement_id, customer_id)
31
- return Main.result_single_object(api_metering.read('entitlement'))
31
+ return Result::SingleObject.new(api_metering.read('entitlement'))
32
32
  end
33
33
  end
34
34
  end