aspera-cli 4.27.2 → 4.27.4

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 (145) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +133 -0
  4. data/CONTRIBUTING.md +5 -2
  5. data/bin/ascli +3 -1
  6. data/docs/README.md +1006 -766
  7. data/lib/aspera/agent/base.rb +7 -2
  8. data/lib/aspera/agent/connect.rb +6 -8
  9. data/lib/aspera/agent/desktop.rb +2 -6
  10. data/lib/aspera/agent/direct.rb +52 -22
  11. data/lib/aspera/agent/node.rb +9 -8
  12. data/lib/aspera/agent/transferd.rb +2 -2
  13. data/lib/aspera/api/alee.rb +1 -1
  14. data/lib/aspera/api/aoc.rb +14 -12
  15. data/lib/aspera/api/ats.rb +1 -1
  16. data/lib/aspera/api/cos_node.rb +2 -2
  17. data/lib/aspera/api/faspex.rb +11 -7
  18. data/lib/aspera/api/httpgw.rb +38 -35
  19. data/lib/aspera/api/node.rb +39 -34
  20. data/lib/aspera/ascmd.rb +3 -1
  21. data/lib/aspera/ascp/installation.rb +63 -28
  22. data/lib/aspera/ascp/management.rb +1 -0
  23. data/lib/aspera/assert.rb +4 -0
  24. data/lib/aspera/cli/ascp_actions.rb +20 -41
  25. data/lib/aspera/cli/async_transfer_store.rb +12 -11
  26. data/lib/aspera/cli/bootstrapper.rb +14 -16
  27. data/lib/aspera/cli/command_line.rb +252 -0
  28. data/lib/aspera/cli/command_registry.rb +215 -37
  29. data/lib/aspera/cli/command_spec.rb +104 -15
  30. data/lib/aspera/cli/completion/ascli.bash +12 -0
  31. data/lib/aspera/cli/completion/ascli.fish +16 -0
  32. data/lib/aspera/cli/completion/ascli.zsh +19 -0
  33. data/lib/aspera/cli/context.rb +3 -0
  34. data/lib/aspera/cli/deprecation.rb +37 -0
  35. data/lib/aspera/cli/extended_value.rb +6 -3
  36. data/lib/aspera/cli/formatter.rb +94 -80
  37. data/lib/aspera/cli/gem_checker.rb +1 -1
  38. data/lib/aspera/cli/hints.rb +7 -6
  39. data/lib/aspera/cli/http.rb +22 -34
  40. data/lib/aspera/cli/info.rb +3 -0
  41. data/lib/aspera/cli/mcp_tool.rb +47 -83
  42. data/lib/aspera/cli/option_declarator.rb +33 -42
  43. data/lib/aspera/cli/option_registry.rb +69 -0
  44. data/lib/aspera/cli/option_types.rb +105 -0
  45. data/lib/aspera/cli/option_value.rb +278 -0
  46. data/lib/aspera/cli/options.schema.yaml +124 -15
  47. data/lib/aspera/cli/parser.rb +333 -862
  48. data/lib/aspera/cli/plugins/alee.rb +7 -4
  49. data/lib/aspera/cli/plugins/aoc.rb +545 -518
  50. data/lib/aspera/cli/plugins/ats.rb +59 -80
  51. data/lib/aspera/cli/plugins/base.rb +221 -265
  52. data/lib/aspera/cli/plugins/basic_auth.rb +2 -10
  53. data/lib/aspera/cli/plugins/config.rb +263 -184
  54. data/lib/aspera/cli/plugins/console.rb +103 -39
  55. data/lib/aspera/cli/plugins/cos.rb +6 -23
  56. data/lib/aspera/cli/plugins/factory.rb +3 -0
  57. data/lib/aspera/cli/plugins/faspex5.rb +204 -182
  58. data/lib/aspera/cli/plugins/faspio.rb +6 -11
  59. data/lib/aspera/cli/plugins/httpgw.rb +8 -11
  60. data/lib/aspera/cli/plugins/mcp.rb +20 -55
  61. data/lib/aspera/cli/plugins/node.rb +300 -327
  62. data/lib/aspera/cli/plugins/orchestrator.rb +152 -110
  63. data/lib/aspera/cli/plugins/preview.rb +96 -105
  64. data/lib/aspera/cli/plugins/server.rb +78 -53
  65. data/lib/aspera/cli/plugins/shares.rb +80 -131
  66. data/lib/aspera/cli/preset_actions.rb +44 -27
  67. data/lib/aspera/cli/preset_manager.rb +44 -19
  68. data/lib/aspera/cli/prompt.rb +36 -0
  69. data/lib/aspera/cli/result.rb +42 -36
  70. data/lib/aspera/cli/runner.rb +32 -59
  71. data/lib/aspera/cli/special_values.rb +5 -0
  72. data/lib/aspera/cli/sync_actions.rb +51 -46
  73. data/lib/aspera/cli/terminal_formatter.rb +9 -3
  74. data/lib/aspera/cli/transfer_actions.rb +14 -9
  75. data/lib/aspera/cli/transfer_agent.rb +34 -38
  76. data/lib/aspera/cli/transfer_progress.rb +290 -55
  77. data/lib/aspera/cli/vault_manager.rb +0 -17
  78. data/lib/aspera/cli/version.rb +1 -1
  79. data/lib/aspera/cli/wizard.rb +5 -3
  80. data/lib/aspera/coverage.rb +1 -1
  81. data/lib/aspera/environment.rb +35 -5
  82. data/lib/aspera/faspex_gw.rb +2 -1
  83. data/lib/aspera/faspex_postproc.rb +1 -0
  84. data/lib/aspera/graphql.rb +5 -5
  85. data/lib/aspera/json_rpc/client.rb +5 -5
  86. data/lib/aspera/keychain/encrypted_hash.rb +2 -2
  87. data/lib/aspera/keychain/factory.rb +2 -1
  88. data/lib/aspera/keychain/one_password_api.rb +1 -1
  89. data/lib/aspera/link_header.rb +2 -2
  90. data/lib/aspera/log.rb +47 -27
  91. data/lib/aspera/markdown.rb +2 -0
  92. data/lib/aspera/mime.rb +25 -0
  93. data/lib/aspera/node_emulator.rb +759 -0
  94. data/lib/aspera/oauth/base.rb +37 -26
  95. data/lib/aspera/oauth/factory.rb +7 -3
  96. data/lib/aspera/oauth/generic.rb +1 -1
  97. data/lib/aspera/oauth/json_credentials.rb +34 -0
  98. data/lib/aspera/oauth/jwt.rb +4 -5
  99. data/lib/aspera/oauth/web.rb +9 -8
  100. data/lib/aspera/oauth.rb +1 -0
  101. data/lib/aspera/persistency_folder.rb +1 -3
  102. data/lib/aspera/preview/file_types.rb +4 -4
  103. data/lib/aspera/preview/generator.rb +11 -1
  104. data/lib/aspera/preview/options.schema.yaml +119 -0
  105. data/lib/aspera/preview/terminal.rb +4 -3
  106. data/lib/aspera/preview/utils.rb +9 -6
  107. data/lib/aspera/products/connect.rb +1 -1
  108. data/lib/aspera/rainbow.rb +7 -0
  109. data/lib/aspera/rest/aspera_errors.rb +72 -0
  110. data/lib/aspera/rest/call_error.rb +27 -0
  111. data/lib/aspera/rest/client.rb +523 -0
  112. data/lib/aspera/rest/error_analyzer.rb +113 -0
  113. data/lib/aspera/rest/list.rb +149 -0
  114. data/lib/aspera/rest/parameters.rb +55 -0
  115. data/lib/aspera/rest/util.rb +176 -0
  116. data/lib/aspera/rest.rb +7 -621
  117. data/lib/aspera/schema/IBM Aspera Console-enhanced.yaml +1125 -0
  118. data/lib/aspera/schema/IBM Aspera Faspex API-5.0-enhanced.yaml +0 -20
  119. data/lib/aspera/schema/IBM Aspera Orchestrator API-v1.yaml +1784 -0
  120. data/lib/aspera/schema/IBM Aspera on Cloud API-0.2.6-enhanced.yaml +1230 -137
  121. data/lib/aspera/schema/IBM Aspera on Cloud Automation API-1.0.5-enhanced.yaml +2395 -0
  122. data/lib/aspera/schema/IBM_Aspera_Shares.yaml +14 -13
  123. data/lib/aspera/schema/documentation.rb +13 -3
  124. data/lib/aspera/schema/reader.rb +12 -18
  125. data/lib/aspera/schema/registry.rb +23 -1
  126. data/lib/aspera/schema/validator.rb +92 -0
  127. data/lib/aspera/secret_hider.rb +36 -25
  128. data/lib/aspera/string_ext.rb +15 -0
  129. data/lib/aspera/temp_file_manager.rb +6 -5
  130. data/lib/aspera/transfer/parameters.rb +2 -0
  131. data/lib/aspera/transfer/spec.rb +1 -0
  132. data/lib/aspera/uri_reader.rb +11 -11
  133. data/lib/aspera/web_auth/index.html +147 -0
  134. data/lib/aspera/web_auth/server.rb +81 -0
  135. data.tar.gz.sig +0 -0
  136. metadata +43 -9
  137. metadata.gz.sig +0 -0
  138. data/lib/aspera/colors.rb +0 -79
  139. data/lib/aspera/node_simulator.rb +0 -344
  140. data/lib/aspera/preview/options.rb +0 -45
  141. data/lib/aspera/rest_call_error.rb +0 -25
  142. data/lib/aspera/rest_error_analyzer.rb +0 -111
  143. data/lib/aspera/rest_errors_aspera.rb +0 -58
  144. data/lib/aspera/rest_list.rb +0 -136
  145. data/lib/aspera/web_auth.rb +0 -211
@@ -18,6 +18,8 @@ require 'yaml'
18
18
  require 'pp'
19
19
  require 'csv'
20
20
  require 'word_wrap'
21
+ require 'aspera/rainbow'
22
+ using Rainbow
21
23
 
22
24
  module Aspera
23
25
  module Cli
@@ -25,7 +27,7 @@ module Aspera
25
27
  class Formatter
26
28
  extend OptionDeclarator
27
29
 
28
- # remove a fields from the list
30
+ # `-` remove a fields from the list
29
31
  FIELDS_LESS = '-'
30
32
  # supported output formats
31
33
  DISPLAY_FORMATS = %i[text nagios ruby json jsonpp yaml table csv image].freeze
@@ -38,17 +40,19 @@ module Aspera
38
40
 
39
41
  private_constant :FIELDS_LESS, :DISPLAY_FORMATS, :DISPLAY_LEVELS, :SINGLE_OBJECT_COLUMN_NAMES, :STR_LST_SEP_VERT
40
42
 
41
- option :out, description: 'Output rendering options (dot-notation: format, level, file, fields, select, table[.pivot], flat, secrets, img)', schema: Schema::Registry::OUT_OPTIONS
42
- option :display, description: 'Output only some information', allowed: DISPLAY_LEVELS, default: :data, deprecation: 'use --out.level'
43
+ option :out, description: 'Output rendering options (dot-notation: format, level, file, fields, select, table[.pivot], flat, secrets, colors, utf8, img)', schema: Schema::Registry::OUT_OPTIONS
44
+ option :display, description: 'Output only some information', allowed: DISPLAY_LEVELS, default: :data, deprecation: {last: '4.27.0', message: 'use --out.level'}
43
45
  option :format, description: 'Output format (also: --out.format)', allowed: DISPLAY_FORMATS, default: :table
44
- option :output, description: 'Destination for results', deprecation: 'use --out.file'
46
+ option :output, description: 'Destination for results', deprecation: {last: '4.27.0', message: 'use --out.file'}
45
47
  option :fields, description: "Comma separated list of: fields, or #{SpecialValues::ALL}, or #{SpecialValues::DEF} (also: --out.fields)", allowed: [String, Array, Regexp, Proc], default: SpecialValues::DEF
46
48
  option :select, description: 'Select only some items in lists: column, value (also: --out.select)', allowed: [Hash, Proc]
47
- option :table_style, description: '(Table) Display style', allowed: [Hash], deprecation: 'use --out.table'
48
- option :flat_hash, description: '(Table) Display deep values as additional keys', allowed: Type::BOOLEAN, default: true, deprecation: 'use --out.flat'
49
- option :multi_single, description: '(Table) Control how object list is displayed as single table, or multiple objects', allowed: %i[no yes single], default: :no, deprecation: 'use --out.table.pivot'
50
- option :show_secrets, description: 'Show secrets on command output', allowed: Type::BOOLEAN, default: false, deprecation: 'use --out.secrets'
51
- option :image, schema: Schema::Registry::IMAGE_OPTIONS, deprecation: 'use --out.img'
49
+ option :table_style, description: '(Table) Display style', allowed: [Hash], deprecation: {last: '4.27.0', message: 'use --out.table'}
50
+ option :flat_hash, description: '(Table) Display deep values as additional keys', allowed: Type::BOOLEAN, default: true, deprecation: {last: '4.27.0', message: 'use --out.flat'}
51
+ option :multi_single, description: '(Table) Control how object list is displayed as single table, or multiple objects', allowed: %i[no yes single], default: :no, deprecation: {last: '4.27.0', message: 'use --out.table.pivot'}
52
+ option :show_secrets, description: 'Show secrets on command output', allowed: Type::BOOLEAN, default: false, deprecation: {last: '4.27.0', message: 'use --out.secrets'}
53
+ option :image, schema: Schema::Registry::IMAGE_OPTIONS, deprecation: {last: '4.27.0', message: 'use --out.img'}
54
+ # All formatter options are handled by `option_handler`, executed on the formatter instance
55
+ option_specs.each_value { |spec| spec.on_set = ->(value) { option_handler(spec.name, value) } }
52
56
 
53
57
  class << self
54
58
  # Replace special values with a readable version on terminal
@@ -85,14 +89,21 @@ module Aspera
85
89
  end
86
90
  end
87
91
 
88
- def all_but(list)
89
- Array(list).map { |i| "#{FIELDS_LESS}#{i}" }.unshift(SpecialValues::ALL)
92
+ # @param fields [Array<String>] List of fields to not display
93
+ # @return [Array<String>] List of fields to display, including special values (`ALL`) and tagged (`-`) fields
94
+ def all_but(*fields)
95
+ Aspera.assert_array_all(fields, String)
96
+ fields.map { |i| "#{FIELDS_LESS}#{i}" }.unshift(SpecialValues::ALL)
90
97
  end
91
98
  end
92
99
 
93
100
  # initialize the formatter
94
101
  def initialize
95
102
  @options = {}
103
+ # Last value of option `out`
104
+ @out_dispatched = {}
105
+ # Colors auto-detected by Rainbow at load time, restored when `--out.colors` is reset
106
+ @colors_detected = Rainbow.enabled
96
107
  @spinner = nil
97
108
  end
98
109
 
@@ -103,7 +114,7 @@ module Aspera
103
114
  total = total.to_i
104
115
  return if total.eql?(0) && count.eql?(0)
105
116
  count_msg = "Items: #{count}/#{total}"
106
- count_msg = count_msg.bg_red unless count.eql?(total)
117
+ count_msg = count_msg.bg(:red) unless count.eql?(total)
107
118
  display_status(count_msg)
108
119
  end
109
120
 
@@ -137,72 +148,68 @@ module Aspera
137
148
  end
138
149
  end
139
150
 
140
- # Bind all formatter options to this instance using set_handler.
151
+ # Declare formatter options on the parser, with `on_set` callbacks executed on this instance.
141
152
  # Called from Runner after Formatter.new.
142
- # @param options [Aspera::Cli::Parser]
153
+ # @param parser [Aspera::Cli::Parser]
143
154
  # @return [nil]
144
- def bind_options(options)
145
- @parser = options
146
- %i[out display format output fields select table_style flat_hash multi_single show_secrets image].each do |opt|
147
- options.set_handler(opt, object: self, method: :option_handler)
148
- end
155
+ def declare_options(parser)
156
+ # Used by `option_handler` to dispatch `--out` sub-options
157
+ @parser = parser
158
+ self.class.declare_options(parser, target: self)
149
159
  nil
150
160
  end
151
161
 
152
- # Getter/setter handler called by the option manager for all formatter options
153
- # @param option_symbol [Symbol] Option name (one of :out, :format, :output, :display, :fields, :select, :table_style, :flat_hash, :multi_single, :show_secrets, :image)
154
- # @param operation [Symbol] :get or :set
155
- # @param value [Object, nil] Value to set (only used when operation is :set)
156
- # @return [Object, nil] Current option value when operation is :get; nil otherwise
157
- def option_handler(option_symbol, operation, value = nil)
158
- Aspera.assert_values(operation, %i[set get])
159
- case operation
160
- when :set
161
- # --out is a composite hash: dispatch each sub-key through the parser (validation included)
162
- if option_symbol.eql?(:out)
163
- Aspera.assert_type(value, Hash)
164
- value.each do |k, v|
165
- case k.to_sym
166
- when :format then @parser.set_option(:format, v, warn_deprecation: false)
167
- when :level then @parser.set_option(:display, v, warn_deprecation: false)
168
- when :file then @parser.set_option(:output, v, warn_deprecation: false)
169
- when :fields then @parser.set_option(:fields, v, warn_deprecation: false)
170
- when :select then @parser.set_option(:select, v, warn_deprecation: false)
171
- when :table
172
- Aspera.assert_type(v, Hash)
173
- table_hash = v.transform_keys(&:to_sym)
174
- @parser.set_option(:multi_single, table_hash.delete(:pivot).to_s, warn_deprecation: false) if table_hash.key?(:pivot)
175
- @parser.set_option(:table_style, table_hash, warn_deprecation: false) unless table_hash.empty?
176
- when :flat then @parser.set_option(:flat_hash, v, warn_deprecation: false)
177
- when :secrets then @parser.set_option(:show_secrets, v, warn_deprecation: false)
178
- when :img then @parser.set_option(:image, v, warn_deprecation: false)
179
- else Aspera.error_unexpected_value(k) { 'out sub-option (format, level, file, fields, select, table[.pivot], flat, secrets, img)' }
180
- end
162
+ # `on_set` callback called by the option manager for all formatter options
163
+ # @param option_symbol [Symbol] Option name (one of :out, :format, :output, :display, :fields, :select, :table_style, :flat_hash, :multi_single, :show_secrets, :image)
164
+ # @param value [Object, nil] New value
165
+ # @return [nil]
166
+ def option_handler(option_symbol, value)
167
+ # --out is a composite hash: dispatch each sub-key through the parser (validation included)
168
+ if option_symbol.eql?(:out)
169
+ Aspera.assert_type(value, Hash)
170
+ # Value is merged with previous values: dispatch only changes
171
+ changed = value.reject { |k, v| @out_dispatched[k].eql?(v) }
172
+ @out_dispatched = value
173
+ changed.each do |k, v|
174
+ case k.to_sym
175
+ when :format then @parser.set_option(:format, v, warn_deprecation: false)
176
+ when :level then @parser.set_option(:display, v, warn_deprecation: false)
177
+ when :file then @parser.set_option(:output, v, warn_deprecation: false)
178
+ when :fields then @parser.set_option(:fields, v, warn_deprecation: false)
179
+ when :select then @parser.set_option(:select, v, warn_deprecation: false)
180
+ when :table
181
+ Aspera.assert_type(v, Hash)
182
+ table_hash = v.transform_keys(&:to_sym)
183
+ @parser.set_option(:multi_single, table_hash.delete(:pivot), warn_deprecation: false) if table_hash.key?(:pivot)
184
+ @parser.set_option(:table_style, table_hash, warn_deprecation: false) unless table_hash.empty?
185
+ when :flat then @parser.set_option(:flat_hash, v, warn_deprecation: false)
186
+ when :secrets then @parser.set_option(:show_secrets, v, warn_deprecation: false)
187
+ when :img then @parser.set_option(:image, v, warn_deprecation: false)
188
+ when :colors then Rainbow.enabled = v.nil? ? @colors_detected : v
189
+ when :utf8 then Environment.unicode = v
190
+ else Aspera.error_unexpected_value(k) { 'out sub-option (format, level, file, fields, select, table[.pivot], flat, secrets, colors, utf8, img)' }
181
191
  end
182
- return
183
192
  end
184
- @options[option_symbol] = value
185
- # special handling of some options
186
- case option_symbol
187
- when :format
188
- @options[:display] = value.eql?(:table) ? :info : :data
189
- when :output
190
- $stdout = if value.eql?('-')
191
- STDOUT # rubocop:disable Style/GlobalStdStream
192
- else
193
- File.open(value, 'w')
194
- end
195
- when :image
196
- # get list if key arguments of method
197
- allowed_options = Preview::Terminal.method(:build).parameters.select { |i| i[0].eql?(:key) }.map { |i| i[1] }
198
- # check that only supported options are given
199
- unknown_options = value.keys.map(&:to_sym) - allowed_options
200
- Aspera.assert(unknown_options.empty?) { "Invalid parameter(s) for option image: #{unknown_options.join(', ')}, use #{allowed_options.join(', ')}" }
193
+ return
194
+ end
195
+ @options[option_symbol] = value
196
+ # special handling of some options
197
+ case option_symbol
198
+ when :format
199
+ # The default output level depends on the format, unless the level is set explicitly (e.g. `--out.level`)
200
+ @options[:display] = value.eql?(:table) ? :info : :data if @parser.nil? || @parser.option_def(:display).source.eql?(:default)
201
+ when :output
202
+ $stdout = if value.eql?('-')
203
+ STDOUT # rubocop:disable Style/GlobalStdStream
204
+ else
205
+ File.open(value, 'w')
201
206
  end
202
- when :get
203
- return if option_symbol.eql?(:out)
204
- return @options[option_symbol]
205
- else Aspera.error_unreachable_line
207
+ when :image
208
+ # get list if key arguments of method
209
+ allowed_options = Preview::Terminal.method(:build).parameters.select { |i| i[0].eql?(:key) }.map { |i| i[1] }
210
+ # check that only supported options are given
211
+ unknown_options = value.keys.map(&:to_sym) - allowed_options
212
+ Aspera.assert(unknown_options.empty?) { "Invalid parameter(s) for option image: #{unknown_options.join(', ')}, use #{allowed_options.join(', ')}" }
206
213
  end
207
214
  nil
208
215
  end
@@ -214,9 +221,9 @@ module Aspera
214
221
  # @param hide_secrets [Boolean] Whether to hide secrets in the message (default: true)
215
222
  # @return [nil]
216
223
  # @note Message display behavior depends on the message_level:
217
- # - +:data+ messages are displayed unless display level is +:error+
218
- # - +:info+ messages are only displayed when display level is +:info+
219
- # - +:error+ messages are always displayed on stderr
224
+ # - `:data` messages are displayed unless display level is `:error`
225
+ # - `:info` messages are only displayed when display level is `:info`
226
+ # - `:error` messages are always displayed on `stderr`
220
227
  def display_message(message_level, message, hide_secrets: true)
221
228
  message = SecretHider.instance.hide_secrets_in_string(message) if hide_secrets && message.is_a?(String) && hide_secrets?
222
229
  case message_level
@@ -291,14 +298,18 @@ module Aspera
291
298
  @options[:image].symbolize_keys
292
299
  end
293
300
 
294
- # @return [Array<String>] all fields of all objects in list of objects
301
+ # Compute the list of all fields for all provided objects
302
+ # @param data [Array<Hash>] objects
303
+ # @return [Array<String>] All fields of all objects in list of objects
295
304
  def all_fields(data)
296
- data.each_with_object({}) { |v, m| v.each_key { |c| m[c] = true } }.keys
305
+ data.flat_map(&:keys).uniq
297
306
  end
298
307
 
299
- # @return [Array<String>] the list of fields to display
300
- # @param data [Array<Hash>] data to display
301
- # @param default [Array<String>, Proc] list of fields to display by default (may contain special values)
308
+ # Given the list of objects (with all fields) and a default filter, including `DEF`, `ALL` and `-`,
309
+ # expand and compute the actual list of fields to display.
310
+ # @param data [Array<Hash>] Data to display
311
+ # @param default [Array<String>, Proc] List of fields to display by default (may contain special values)
312
+ # @return [Array<String>] List of fields to display
302
313
  def compute_fields(data, default)
303
314
  Log.log.debug { "compute_fields: data:#{data.class} default:#{default.class} #{default}" }
304
315
  Log.dump(:compute_fields_default, default, level: :trace1)
@@ -355,8 +366,9 @@ module Aspera
355
366
  return data.map { |i| i.slice(*selected_fields) }
356
367
  end
357
368
 
358
- # filter the list of items on the select option
359
- # @param data [Array<Hash>] list of items
369
+ # Filter the list of items on the select option
370
+ # @param data [Array<Hash>] List of items
371
+ # @return [nil]
360
372
  def filter_columns_on_select(data)
361
373
  case @options[:select]
362
374
  when Proc
@@ -368,12 +380,14 @@ module Aspera
368
380
  when Hash
369
381
  @options[:select].each { |k, v| data.select! { |i| i[k].eql?(v) } }
370
382
  end
383
+ nil
371
384
  end
372
385
 
373
386
  # Displays a list of objects
374
387
  # @param object_array [Array<Hash>] Array of hash
375
388
  # @param fields [Array<String>] List of column names
376
389
  # @param single [Boolean] Contains a single object to display
390
+ # @return [nil]
377
391
  def display_table(object_array, fields, single: false)
378
392
  Aspera.assert_array_all(object_array, Hash)
379
393
  Aspera.assert_array_all(fields, String)
@@ -19,7 +19,7 @@ module Aspera
19
19
  def check_gem_version
20
20
  latest_version =
21
21
  begin
22
- Rest.new(base_url: 'https://rubygems.org/api/v1').read("versions/#{Info::GEM_NAME}/latest.json")['version']
22
+ Rest::Client.new(base_url: 'https://rubygems.org/api/v1').read("versions/#{Info::GEM_NAME}/latest.json")['version']
23
23
  rescue StandardError
24
24
  Log.log.warn('Could not retrieve latest gem version on rubygems.')
25
25
  '0'
@@ -6,6 +6,7 @@ require 'aspera/log'
6
6
  require 'aspera/ssh'
7
7
  require 'aspera/assert'
8
8
  require 'aspera/cli/info'
9
+ require 'aspera/cli/terminal_formatter'
9
10
  require 'net/ssh'
10
11
  require 'openssl'
11
12
 
@@ -26,7 +27,7 @@ module Aspera
26
27
  ]
27
28
  },
28
29
  {
29
- exception: Aspera::RestCallError,
30
+ exception: Aspera::Rest::CallError,
30
31
  match: /Signature has expired/,
31
32
  remediation: [
32
33
  'There is too much time difference between your computer and the server',
@@ -70,7 +71,7 @@ module Aspera
70
71
  ]
71
72
  },
72
73
  {
73
- exception: Aspera::RestCallError,
74
+ exception: Aspera::Rest::CallError,
74
75
  match: /Invalid subject\./,
75
76
  remediation: [
76
77
  'It seems that this user name is not registered on the server',
@@ -102,7 +103,7 @@ module Aspera
102
103
  ]
103
104
  },
104
105
  {
105
- exception: Aspera::RestCallError,
106
+ exception: Aspera::Rest::CallError,
106
107
  match: /Server is not configured for this request/,
107
108
  remediation: [
108
109
  'Transfer user shall have those parameters in aspera.conf set to: token',
@@ -110,14 +111,14 @@ module Aspera
110
111
  ]
111
112
  },
112
113
  {
113
- exception: Aspera::RestCallError,
114
+ exception: Aspera::Rest::CallError,
114
115
  match: /invalid_grant/,
115
116
  remediation: [
116
117
  'Check your public key in your AoC user profile.'
117
118
  ]
118
119
  },
119
120
  {
120
- exception: Aspera::RestCallError,
121
+ exception: Aspera::Rest::CallError,
121
122
  match: /Please configure ACLs for this URI/,
122
123
  remediation: [
123
124
  'server must have: asnodeadmin -mu <node user> --acl-add=internal --internal'
@@ -145,7 +146,7 @@ module Aspera
145
146
  else Aspera.error_unexpected_value(m) { 'hint match' }
146
147
  end
147
148
  hint[:remediation].each do |r|
148
- Log.log.info { "#{'HINT:'.bg_green.gray.blink.freeze} #{r}" }
149
+ Log.log.info { "#{TerminalFormatter.hint} #{r}" }
149
150
  end
150
151
  end
151
152
  end
@@ -26,12 +26,13 @@ module Aspera
26
26
 
27
27
  private_constant :CERT_EXT, :SELF_SIGNED_CERT
28
28
 
29
- option :insecure, description: 'HTTP/S: Do not validate any certificate', allowed: Type::BOOLEAN, default: false
30
- option :ignore_certificate, description: 'HTTP/S: Do not validate certificate for these URLs', allowed: [Array, NilClass]
31
- option :warn_insecure, description: 'HTTP/S: Issue a warning if certificate is ignored', allowed: Type::BOOLEAN, default: true
32
- option :cert_stores, description: 'HTTP/S: List of folder with trusted certificates', allowed: Type::STRING_ARRAY
33
- option :http_options, schema: Schema::Registry::HTTP_OPTIONS
34
- option :http_proxy, description: 'HTTP/S: URL for proxy with optional credentials'
29
+ # `on_set` callbacks are methods of the instance given as `target:` to `declare_options`
30
+ option :insecure, description: 'HTTP/S: Do not validate any certificate', allowed: Type::BOOLEAN, default: false, on_set: :insecure=
31
+ option :ignore_certificate, description: 'HTTP/S: Do not validate certificate for these URLs', allowed: [Array, NilClass], on_set: :ignore_cert_host_port=
32
+ option :warn_insecure, description: 'HTTP/S: Issue a warning if certificate is ignored', allowed: Type::BOOLEAN, default: true, on_set: :warn_insecure=
33
+ option :cert_stores, description: 'HTTP/S: List of folder with trusted certificates', allowed: Type::STRING_ARRAY, on_set: :trusted_cert_locations=
34
+ option :http_options, schema: Schema::Registry::HTTP_OPTIONS, on_set: :http_options=
35
+ option :http_proxy, description: 'HTTP/S: URL for proxy with optional credentials', on_set: :http_proxy=
35
36
 
36
37
  def initialize
37
38
  @insecure = false
@@ -46,21 +47,8 @@ module Aspera
46
47
  attr_accessor :insecure, :warn_insecure
47
48
  attr_reader :ignore_cert_host_port, :http_options
48
49
 
49
- # Bind all HTTP options to this instance using set_handler.
50
- # Called from Config#initialize immediately after Http.new.
51
- # @param options [Aspera::Cli::Parser]
52
- # @return [nil]
53
- def bind_options(options)
54
- options.set_handler(:insecure, object: self, method: :insecure)
55
- options.set_handler(:ignore_certificate, object: self, method: :ignore_cert_host_port)
56
- options.set_handler(:warn_insecure, object: self, method: :warn_insecure)
57
- options.set_handler(:cert_stores, object: self, method: :trusted_cert_locations)
58
- options.set_handler(:http_options, object: self, method: :http_options)
59
- options.set_handler(:http_proxy, object: self, method: :http_proxy)
60
- end
61
-
62
50
  # Setter for http_options: dispatch each key to its target singleton immediately.
63
- # Keys matching RestParameters setters go to RestParameters, 'ssl_options' goes to SSL,
51
+ # Keys matching Rest::Parameters setters go to Rest::Parameters, 'ssl_options' goes to SSL,
64
52
  # keys matching OAuth::Factory.instance.parameters go to OAuth, and the rest are kept
65
53
  # in @http_options for Net::HTTP session configuration in update_session.
66
54
  # This runs on every assignment (JSON hash, dotted notation, preset merge) so timing
@@ -72,8 +60,8 @@ module Aspera
72
60
  kept = {}
73
61
  new_options.each do |k, v|
74
62
  method = "#{k}=".to_sym
75
- if RestParameters.instance.respond_to?(method)
76
- RestParameters.instance.send(method, v)
63
+ if Rest::Parameters.instance.respond_to?(method)
64
+ Rest::Parameters.instance.send(method, v)
77
65
  elsif k.to_s.eql?('ssl_options')
78
66
  Aspera::SSL.option_list = v
79
67
  elsif OAuth::Factory.instance.parameters.key?(k.to_sym)
@@ -90,10 +78,6 @@ module Aspera
90
78
  # Proxy
91
79
  # ------------------------------------------------------------------
92
80
 
93
- def http_proxy
94
- ENV['http_proxy']
95
- end
96
-
97
81
  def http_proxy=(value)
98
82
  URI.parse(value)
99
83
  ENV['http_proxy'] = value
@@ -103,11 +87,12 @@ module Aspera
103
87
  # Per-URL certificate ignore list
104
88
  # ------------------------------------------------------------------
105
89
 
90
+ # @param url_list [Array<String>, nil] URLs for which certificate is not validated
106
91
  def ignore_cert_host_port=(url_list)
107
- url_list.each do |url|
92
+ @ignore_cert_host_port = (url_list || []).map do |url|
108
93
  uri = URI.parse(url)
109
94
  Aspera.assert(uri.scheme.eql?('https')) { "Expecting https scheme: #{url}" }
110
- @ignore_cert_host_port.push([uri.host, uri.port].freeze)
95
+ [uri.host, uri.port].freeze
111
96
  end
112
97
  end
113
98
 
@@ -134,13 +119,16 @@ module Aspera
134
119
  # Add files, folders or the default OS locations to the cert store.
135
120
  # @param path_list [Array<String>] list of file/folder paths to add to the certificate store
136
121
  # @return [nil]
122
+ # Replace the certificate store with the given locations
123
+ # @param path_list [Array<String>] files or folders, or `DEF` for system default; empty: system default
137
124
  def trusted_cert_locations=(path_list)
138
125
  Aspera.assert_type(path_list, Array) { 'cert locations' }
139
- if @certificate_store.nil?
140
- Log.log.debug('Creating SSL Cert store')
141
- @certificate_store = OpenSSL::X509::Store.new
142
- @certificate_paths = []
143
- end
126
+ # Empty: lazily initialized with system default
127
+ @certificate_store = @certificate_paths = nil
128
+ return if path_list.empty?
129
+ Log.log.debug('Creating SSL Cert store')
130
+ @certificate_store = OpenSSL::X509::Store.new
131
+ @certificate_paths = []
144
132
  path_list.each do |path|
145
133
  Aspera.assert_type(path, String) { 'Expecting a String for certificate location' }
146
134
  paths_to_add = [path]
@@ -148,7 +136,7 @@ module Aspera
148
136
  if path.eql?(SpecialValues::DEF)
149
137
  @certificate_store.set_default_paths
150
138
  paths_to_add = [OpenSSL::X509::DEFAULT_CERT_DIR]
151
- paths_to_add.push(OpenSSL::X509::DEFAULT_CERT_FILE) unless defined?(JRUBY_VERSION)
139
+ paths_to_add.push(ENV.fetch(OpenSSL::X509::DEFAULT_CERT_FILE_ENV, OpenSSL::X509::DEFAULT_CERT_FILE)) unless defined?(JRUBY_VERSION)
152
140
  paths_to_add.select! { |f| File.exist?(f) }
153
141
  elsif File.file?(path)
154
142
  @certificate_store.add_file(path)
@@ -17,6 +17,9 @@ module Aspera
17
17
  RUBY_FUTURE_MINIMUM_VERSION = '3.2'
18
18
  # Version with which this version of CLI was tested
19
19
  SDK_VERSION = '1.1.9'
20
+ # RubyInstaller version packaged in the Windows installer zip (release tag without `RubyInstaller-` prefix)
21
+ # https://github.com/oneclick/rubyinstaller2/releases
22
+ WINDOWS_RUBY_INSTALLER_VERSION = '4.0.7-1'
20
23
  end
21
24
  end
22
25
  end