aspera-cli 4.27.5 → 4.28.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.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +160 -4
  4. data/CONTRIBUTING.md +4 -2
  5. data/README.md +1 -1
  6. data/bin/asession +1 -1
  7. data/docs/README.md +1086 -331
  8. data/docs/test-mcp-with-ai.md +5 -3
  9. data/lib/aspera/agent/direct.rb +15 -4
  10. data/lib/aspera/agent/factory.rb +2 -1
  11. data/lib/aspera/agent/node.rb +1 -1
  12. data/lib/aspera/api/cos_node.rb +1 -1
  13. data/lib/aspera/api/faspex.rb +1 -1
  14. data/lib/aspera/api/node.rb +6 -2
  15. data/lib/aspera/ascp/installation.rb +47 -11
  16. data/lib/aspera/ascp/management.rb +89 -43
  17. data/lib/aspera/cli/ascp_actions.rb +5 -19
  18. data/lib/aspera/cli/bootstrapper.rb +1 -2
  19. data/lib/aspera/cli/command_registry.rb +43 -3
  20. data/lib/aspera/cli/command_spec.rb +3 -0
  21. data/lib/aspera/cli/completion/ascli.bash +39 -5
  22. data/lib/aspera/cli/completion/ascli.fish +16 -8
  23. data/lib/aspera/cli/completion/ascli.ps1 +41 -0
  24. data/lib/aspera/cli/completion/ascli.zsh +20 -4
  25. data/lib/aspera/cli/completion_actions.rb +360 -0
  26. data/lib/aspera/cli/error.rb +42 -0
  27. data/lib/aspera/cli/extended_value.rb +30 -5
  28. data/lib/aspera/cli/formatter.rb +118 -56
  29. data/lib/aspera/cli/hints.rb +0 -1
  30. data/lib/aspera/cli/http.rb +6 -5
  31. data/lib/aspera/cli/info.rb +10 -4
  32. data/lib/aspera/cli/mailer.rb +1 -1
  33. data/lib/aspera/cli/mcp/http_servlet.rb +156 -0
  34. data/lib/aspera/cli/mcp/secrets.rb +143 -0
  35. data/lib/aspera/cli/mcp/tool.rb +231 -0
  36. data/lib/aspera/cli/option_value.rb +9 -1
  37. data/lib/aspera/cli/options.schema.yaml +390 -39
  38. data/lib/aspera/cli/parser.rb +14 -5
  39. data/lib/aspera/cli/plugins/aoc.rb +8 -11
  40. data/lib/aspera/cli/plugins/base.rb +36 -15
  41. data/lib/aspera/cli/plugins/config.rb +15 -44
  42. data/lib/aspera/cli/plugins/console.rb +3 -1
  43. data/lib/aspera/cli/plugins/factory.rb +1 -1
  44. data/lib/aspera/cli/plugins/faspex5.rb +9 -19
  45. data/lib/aspera/cli/plugins/faspio.rb +36 -5
  46. data/lib/aspera/cli/plugins/httpgw.rb +1 -0
  47. data/lib/aspera/cli/plugins/mcp.rb +177 -118
  48. data/lib/aspera/cli/plugins/node.rb +14 -8
  49. data/lib/aspera/cli/plugins/orchestrator.rb +351 -38
  50. data/lib/aspera/cli/plugins/server.rb +3 -1
  51. data/lib/aspera/cli/plugins/shares.rb +205 -35
  52. data/lib/aspera/cli/preset_actions.rb +15 -7
  53. data/lib/aspera/cli/preset_manager.rb +24 -2
  54. data/lib/aspera/cli/prompt.rb +3 -1
  55. data/lib/aspera/cli/result.rb +17 -4
  56. data/lib/aspera/cli/runner.rb +133 -43
  57. data/lib/aspera/cli/security.rb +134 -0
  58. data/lib/aspera/cli/table_fitter.rb +116 -0
  59. data/lib/aspera/cli/terminal_formatter.rb +23 -34
  60. data/lib/aspera/cli/transfer_agent.rb +4 -1
  61. data/lib/aspera/cli/vault_manager.rb +6 -5
  62. data/lib/aspera/cli/version.rb +1 -1
  63. data/lib/aspera/cli/web_secret.html.erb +61 -0
  64. data/lib/aspera/cli/web_secret.rb +220 -0
  65. data/lib/aspera/cli/wizard.rb +19 -9
  66. data/lib/aspera/command_line_builder.rb +26 -0
  67. data/lib/aspera/data_repository.rb +38 -24
  68. data/lib/aspera/duration.rb +42 -0
  69. data/lib/aspera/environment.rb +88 -24
  70. data/lib/aspera/exec_spec.rb +6 -5
  71. data/lib/aspera/faspex_gw.rb +98 -32
  72. data/lib/aspera/faspex_postproc.rb +187 -44
  73. data/lib/aspera/formatter_interface.rb +0 -1
  74. data/lib/aspera/id_generator.rb +2 -1
  75. data/lib/aspera/json_rpc/client.rb +51 -32
  76. data/lib/aspera/json_rpc/version.rb +1 -0
  77. data/lib/aspera/keychain/base.rb +5 -0
  78. data/lib/aspera/keychain/encrypted_hash.rb +6 -2
  79. data/lib/aspera/keychain/factory.rb +2 -3
  80. data/lib/aspera/keychain/hashicorp_vault.rb +7 -4
  81. data/lib/aspera/keychain/macos_security.rb +119 -13
  82. data/lib/aspera/keychain/one_password_api.rb +8 -3
  83. data/lib/aspera/keychain/one_password_base.rb +14 -9
  84. data/lib/aspera/keychain/one_password_cli.rb +4 -2
  85. data/lib/aspera/log.rb +3 -6
  86. data/lib/aspera/markdown.rb +152 -115
  87. data/lib/aspera/mime.rb +6 -0
  88. data/lib/aspera/nagios.rb +3 -1
  89. data/lib/aspera/node_emulator.rb +98 -101
  90. data/lib/aspera/oauth/{base.rb → client/base.rb} +5 -4
  91. data/lib/aspera/oauth/{boot.rb → client/boot.rb} +3 -2
  92. data/lib/aspera/oauth/{factory.rb → client/factory.rb} +7 -0
  93. data/lib/aspera/oauth/{generic.rb → client/generic.rb} +1 -1
  94. data/lib/aspera/oauth/{json_credentials.rb → client/json_credentials.rb} +1 -1
  95. data/lib/aspera/oauth/{jwt.rb → client/jwt.rb} +1 -1
  96. data/lib/aspera/oauth/{url_json.rb → client/url_json.rb} +1 -1
  97. data/lib/aspera/oauth/{web.rb → client/web.rb} +2 -2
  98. data/lib/aspera/oauth/server/authorize.html.erb +34 -0
  99. data/lib/aspera/oauth/server/pkce.rb +426 -0
  100. data/lib/aspera/orchestrator_workflow_checker.rb +561 -0
  101. data/lib/aspera/preview/terminal.rb +3 -2
  102. data/lib/aspera/rainbow.rb +27 -1
  103. data/lib/aspera/rest/aspera_errors.rb +51 -59
  104. data/lib/aspera/rest/client.rb +21 -14
  105. data/lib/aspera/rest/error_analyzer.rb +9 -0
  106. data/lib/aspera/rest/list.rb +6 -6
  107. data/lib/aspera/rest/util.rb +7 -1
  108. data/lib/aspera/rest.rb +0 -1
  109. data/lib/aspera/schema/IBM Aspera Faspex API-5.0-enhanced.yaml +0 -2
  110. data/lib/aspera/schema/IBM Aspera Orchestrator API-v1-enhanced.yaml +4001 -0
  111. data/lib/aspera/schema/IBM Aspera faspio Gateway API-1.0.0-enhanced.yaml +1097 -0
  112. data/lib/aspera/schema/IBM Aspera on Cloud Automation API-1.0.5-enhanced.yaml +35 -35
  113. data/lib/aspera/schema/IBM_Aspera_Shares.yaml +819 -7
  114. data/lib/aspera/schema/documentation.rb +50 -78
  115. data/lib/aspera/schema/reader.rb +39 -11
  116. data/lib/aspera/schema/registry.rb +8 -2
  117. data/lib/aspera/secret_hider.rb +94 -15
  118. data/lib/aspera/secret_strength.rb +114 -0
  119. data/lib/aspera/servlet_helpers.rb +111 -0
  120. data/lib/aspera/sync/args.schema.yaml +3 -1
  121. data/lib/aspera/sync/conf.schema.yaml +16 -6
  122. data/lib/aspera/sync/operations.rb +21 -1
  123. data/lib/aspera/temp_file_manager.rb +79 -20
  124. data/lib/aspera/transfer/parameters.rb +5 -0
  125. data/lib/aspera/transfer/spec.rb +52 -12
  126. data/lib/aspera/transfer/spec.schema.yaml +8 -5
  127. data/lib/aspera/web_auth/index.html.erb +16 -0
  128. data/lib/aspera/web_auth/server.rb +18 -10
  129. data/lib/aspera/web_page.html.erb +262 -0
  130. data/lib/aspera/web_page.rb +61 -0
  131. data/lib/aspera/web_server_simple.rb +76 -10
  132. data.tar.gz.sig +0 -0
  133. metadata +47 -32
  134. metadata.gz.sig +0 -0
  135. data/lib/aspera/cli/mcp_tool.rb +0 -189
  136. data/lib/aspera/oauth.rb +0 -9
  137. data/lib/aspera/schema/IBM Aspera Orchestrator API-v1.yaml +0 -1784
  138. data/lib/aspera/schema/IBM Aspera faspio Gateway API-1.0.0.yaml +0 -249
  139. data/lib/aspera/web_auth/index.html +0 -147
@@ -1,71 +1,63 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'aspera/rest/error_analyzer'
4
- require 'aspera/log'
5
4
  require 'xmlsimple'
6
5
 
7
6
  module Aspera
8
7
  module Rest
9
- # REST error handlers for various Aspera REST APIs
10
- class AsperaErrors
11
- class << self
12
- # handlers should probably be defined by plugins for modularity
13
- def register_handlers
14
- Log.log.debug('registering Aspera REST error handlers')
15
- # Faspex 4: both user_message and internal_message, and code 200
16
- # example: missing meta data on package creation
17
- ErrorAnalyzer.instance.add_simple_handler(name: 'Type 1: error:user_message', path: %w[error user_message], always: true)
18
- ErrorAnalyzer.instance.add_simple_handler(name: 'Type 2: error:description', path: %w[error description])
19
- ErrorAnalyzer.instance.add_simple_handler(name: 'Type 3: error:internal_message', path: %w[error internal_message])
20
- ErrorAnalyzer.instance.add_simple_handler(name: 'Type 5', path: ['error_description'])
21
- ErrorAnalyzer.instance.add_simple_handler(name: 'Type 6', path: ['message'])
22
- ErrorAnalyzer.instance.add_simple_handler(name: 'Type 6', path: ['failure'], always: true)
23
- # AoC Automation
24
- ErrorAnalyzer.instance.add_simple_handler(name: 'AoC Automation', path: ['error'])
25
- ErrorAnalyzer.instance.add_handler('Type 7: errors[]') do |type, context|
26
- next unless context[:data].is_a?(Hash) && context[:data]['errors'].is_a?(Hash)
27
- # special for Shares: false positive ? (update global transfer_settings)
28
- next if context[:data].key?('min_connect_version')
29
- context[:data]['errors'].each do |k, v|
30
- ErrorAnalyzer.add_error(context, type, "#{k}: #{v}")
31
- end
32
- end
33
- # call to upload_setup and download_setup of node api
34
- ErrorAnalyzer.instance.add_handler('T8:node: *_setup') do |type, context|
35
- next unless context[:data].is_a?(Hash)
36
- d_t_s = context[:data]['transfer_specs']
37
- next unless d_t_s.is_a?(Array)
38
- d_t_s.each do |res|
39
- r_err = res.dig(*%w[transfer_spec error]) || res['error']
40
- next unless r_err.is_a?(Hash)
41
- ErrorAnalyzer.add_error(context, type, r_err.values.join(': '))
42
- end
43
- end
44
- ErrorAnalyzer.instance.add_simple_handler(name: 'T9:IBM cloud IAM', path: ['errorMessage'])
45
- ErrorAnalyzer.instance.add_simple_handler(name: 'T10:faspex v4', path: ['user_message'])
46
- ErrorAnalyzer.instance.add_handler('Orchestrator') do |type, context|
47
- next if context[:response].code.start_with?('2')
48
- data = context[:data]
49
- if data.is_a?(String) && data.start_with?('<?xml')
50
- parsed = XmlSimple.xml_in(data, {'ForceArray' => false}) rescue nil
51
- if parsed.is_a?(Hash) && parsed['content'].is_a?(String)
52
- ErrorAnalyzer.add_error(context, type, parsed['content'].gsub(/\A"|"\z/, ''))
53
- parsed.each do |k, v|
54
- next if k.eql?('content')
55
- ErrorAnalyzer.add_error(context, "#{type}(sub)", "#{k}: #{v}") if [String, Integer].include?(v.class)
56
- end
57
- end
58
- next
59
- end
60
- next unless data.is_a?(Hash)
61
- work_order = data['work_order']
62
- next unless work_order.is_a?(Hash)
63
- ErrorAnalyzer.add_error(context, type, work_order['statusDetails'])
64
- data['missing_parameters']&.each do |param|
65
- ErrorAnalyzer.add_error(context, type, "missing parameter: #{param}")
66
- end
8
+ # REST error handlers for various Aspera REST APIs, registered on require
9
+ # handlers should probably be defined by plugins for modularity
10
+ # Faspex 4: both user_message and internal_message, and code 200
11
+ # example: missing meta data on package creation
12
+ ErrorAnalyzer.instance.add_simple_handler(name: 'Type 1: error:user_message', path: %w[error user_message], always: true)
13
+ ErrorAnalyzer.instance.add_simple_handler(name: 'Type 2: error:description', path: %w[error description])
14
+ ErrorAnalyzer.instance.add_simple_handler(name: 'Type 3: error:internal_message', path: %w[error internal_message])
15
+ ErrorAnalyzer.instance.add_simple_handler(name: 'Type 5', path: ['error_description'])
16
+ ErrorAnalyzer.instance.add_simple_handler(name: 'Type 6', path: ['message'])
17
+ ErrorAnalyzer.instance.add_simple_handler(name: 'Type 6', path: ['failure'], always: true)
18
+ # AoC Automation
19
+ ErrorAnalyzer.instance.add_simple_handler(name: 'AoC Automation', path: ['error'])
20
+ ErrorAnalyzer.instance.add_handler('Type 7: errors[]') do |type, context|
21
+ next unless context[:data].is_a?(Hash) && context[:data]['errors'].is_a?(Hash)
22
+ # special for Shares: false positive ? (update global transfer_settings)
23
+ next if context[:data].key?('min_connect_version')
24
+ context[:data]['errors'].each do |k, v|
25
+ ErrorAnalyzer.add_error(context, type, "#{k}: #{v}")
26
+ end
27
+ end
28
+ # call to upload_setup and download_setup of node api
29
+ ErrorAnalyzer.instance.add_handler('T8:node: *_setup') do |type, context|
30
+ next unless context[:data].is_a?(Hash)
31
+ d_t_s = context[:data]['transfer_specs']
32
+ next unless d_t_s.is_a?(Array)
33
+ d_t_s.each do |res|
34
+ r_err = res.dig(*%w[transfer_spec error]) || res['error']
35
+ next unless r_err.is_a?(Hash)
36
+ ErrorAnalyzer.add_error(context, type, r_err.values.join(': '))
37
+ end
38
+ end
39
+ ErrorAnalyzer.instance.add_simple_handler(name: 'T9:IBM cloud IAM', path: ['errorMessage'])
40
+ ErrorAnalyzer.instance.add_simple_handler(name: 'T10:faspex v4', path: ['user_message'])
41
+ ErrorAnalyzer.instance.add_handler('Orchestrator') do |type, context|
42
+ next if context[:response].code.start_with?('2')
43
+ data = context[:data]
44
+ if data.is_a?(String) && data.start_with?('<?xml')
45
+ parsed = XmlSimple.xml_in(data, {'ForceArray' => false}) rescue nil
46
+ if parsed.is_a?(Hash) && parsed['content'].is_a?(String)
47
+ ErrorAnalyzer.add_error(context, type, parsed['content'].gsub(/\A"|"\z/, ''))
48
+ parsed.each do |k, v|
49
+ next if k.eql?('content')
50
+ ErrorAnalyzer.add_error(context, "#{type}(sub)", "#{k}: #{v}") if [String, Integer].include?(v.class)
67
51
  end
68
52
  end
53
+ next
54
+ end
55
+ next unless data.is_a?(Hash)
56
+ work_order = data['work_order']
57
+ next unless work_order.is_a?(Hash)
58
+ ErrorAnalyzer.add_error(context, type, work_order['statusDetails'])
59
+ data['missing_parameters']&.each do |param|
60
+ ErrorAnalyzer.add_error(context, type, "missing parameter: #{param}")
69
61
  end
70
62
  end
71
63
  end
@@ -5,10 +5,9 @@ require 'aspera/rest/parameters'
5
5
  require 'aspera/rest/util'
6
6
  require 'aspera/rest/call_error'
7
7
  require 'aspera/rest/error_analyzer'
8
- require 'aspera/rest/aspera_errors'
9
8
  require 'aspera/log'
10
9
  require 'aspera/assert'
11
- require 'aspera/oauth'
10
+ require 'aspera/oauth/client/factory'
12
11
  require 'aspera/hash_ext'
13
12
  require 'aspera/timer_limiter'
14
13
  require 'net/http'
@@ -126,11 +125,12 @@ module Aspera
126
125
  # @param subpath [String] subpath of REST API
127
126
  # @param query [Hash{String,Symbol => Object}] URL parameters
128
127
  # @param content_type [String, nil] Type of body parameters (one of MIME_*) and serialization, else use headers
129
- # @param body [Hash, String, nil] Body parameters
128
+ # @param body [Hash, Array, String, nil] Body parameters (see `build_request`)
130
129
  # @param headers [Hash{String => String}] Additional headers (override Content-Type)
131
130
  # @param save_to [String, Pathname, IO, nil] File path or IO object to save response body; progress bar is used when set
132
131
  # @param exception [Boolean] Whether to raise an exception on HTTP error
133
132
  # @param ret [Symbol] One of :data, :resp, :both - controls return value
133
+ # @param json_opts [Hash] Options of `JSON.parse` for a JSON response, e.g. `{allow_duplicate_key: true}`
134
134
  # @return [Array(Hash, Net::HTTPResponse)] When `ret` is :both
135
135
  # @return [Net::HTTPResponse] When `ret` is :resp
136
136
  # @return [Hash] When `ret` is :data
@@ -144,7 +144,8 @@ module Aspera
144
144
  headers: nil,
145
145
  save_to: nil,
146
146
  exception: true,
147
- ret: :data
147
+ ret: :data,
148
+ json_opts: {}
148
149
  )
149
150
  subpath = subpath.to_s if subpath.is_a?(Symbol)
150
151
  subpath = '' if subpath.nil?
@@ -185,7 +186,7 @@ module Aspera
185
186
  # TODO : related to mime type encoding ?
186
187
  # result_http.body.force_encoding('UTF-8') if result_http.body.is_a?(String)
187
188
  # Log.log.debug{"result: body=#{result_http.body}"}
188
- result_data = parse_response(result_http, result_mime)
189
+ result_data = parse_response(result_http, mime_type: result_mime, json_opts: json_opts)
189
190
  ErrorAnalyzer.instance.raise_on_error(req, result_data, result_http)
190
191
  unless file_saved || save_to.nil?
191
192
  raise 'save_to: IO object requires a streaming response' if save_to.respond_to?(:write)
@@ -223,7 +224,8 @@ module Aspera
223
224
  save_to: save_to,
224
225
  exception: exception,
225
226
  headers: headers,
226
- ret: ret
227
+ ret: ret,
228
+ json_opts: json_opts
227
229
  )
228
230
  end
229
231
  # raise exception if could not retry and not return error in result
@@ -339,8 +341,9 @@ module Aspera
339
341
  # @param operation [String] HTTP operation (GET, POST, ...)
340
342
  # @param subpath [String] Subpath of REST API
341
343
  # @param query [Hash, String, Array, nil] Query of request
342
- # @param content_type [String, nil] One of Mime::JSON, Mime::WWW, Mime::TEXT, or `nil` for no body
343
- # @param body [Hash, String, nil] Body of request, serialized according to `content_type`
344
+ # @param content_type [String, nil] One of Mime::JSON, Mime::WWW, Mime::TEXT, Mime::MULTIPART, or `nil` for no body
345
+ # @param body [Hash, Array, String, nil] Body of request, serialized according to `content_type`
346
+ # For Mime::MULTIPART: Hash `name => value`, or Array of `[name, value, opts]` with opts `filename`, `content_type` for a file part
344
347
  # @param headers [Hash] Headers of request
345
348
  # @return [Net::HTTPRequest] The request
346
349
  def build_request(operation, subpath, query, content_type, body, headers)
@@ -366,6 +369,9 @@ module Aspera
366
369
  when Mime::TEXT
367
370
  req.body = body
368
371
  req['Content-Type'] = Mime::TEXT
372
+ when Mime::MULTIPART
373
+ # values are kept in the request: re-sent on retry
374
+ req.set_form(body.to_a, Mime::MULTIPART)
369
375
  else Aspera.error_unexpected_value(content_type) { 'body type' }
370
376
  end
371
377
  # set headers
@@ -438,17 +444,18 @@ module Aspera
438
444
  end
439
445
 
440
446
  # Parse response body, according to media type
441
- # @param result_http [Net::HTTPResponse] Response
442
- # @param result_mime [String] Media type of response
447
+ # @param http_res [Net::HTTPResponse] Response
448
+ # @param mime_type [String] Media type of response
449
+ # @param json_opts [Hash] Options of `JSON.parse`
443
450
  # @return [Hash, Array, String, nil] Parsed JSON, or raw body
444
- def parse_response(result_http, result_mime)
445
- result_data = result_http.body
451
+ def parse_response(http_res, mime_type:, json_opts: {})
452
+ result_data = http_res.body
446
453
  Log.dump(:result_data_raw, result_data, level: :trace1)
447
454
  # TODO: Remove next 2 lines when bug in async node api is fixed. (Aspera/core/issues/4490)
448
455
  node_api_bug = result_data&.index('}HTTP/1.1 400 Bad Request') if result_data.is_a?(String)
449
456
  result_data = result_data[0..node_api_bug] if node_api_bug
450
- result_mime = 'application/xml' if result_data.is_a?(String) && result_data.start_with?('<?xml')
451
- result_data = JSON.parse(result_data) if Mime.json?(result_mime) && !result_data.nil? && !result_data.empty?
457
+ mime_type = 'application/xml' if result_data.is_a?(String) && result_data.start_with?('<?xml')
458
+ result_data = JSON.parse(result_data, **json_opts) if Mime.json?(mime_type) && !result_data.nil? && !result_data.empty?
452
459
  Log.dump(:result_data, result_data)
453
460
  result_data
454
461
  end
@@ -15,6 +15,10 @@ module Aspera
15
15
  class ErrorAnalyzer
16
16
  include Singleton
17
17
 
18
+ # Line of the backtrace of a Ruby exception (Exception#full_message), e.g. `\tfrom /app/x.rb:12:in 'y'`
19
+ BACKTRACE_LINE = /^\s+from \S.*:\d+:in /
20
+ private_constant :BACKTRACE_LINE
21
+
18
22
  attr_accessor :log_file
19
23
 
20
24
  # the singleton object is registered with application specific handlers
@@ -97,6 +101,11 @@ module Aspera
97
101
  # @param type [String] type of exception, for logging purpose
98
102
  # @param message [String] one error message to add to list
99
103
  def add_error(context, type, message)
104
+ # A server in Ruby (e.g. Orchestrator) can return the backtrace of the exception: in debug log only
105
+ if message.is_a?(String) && message.match?(BACKTRACE_LINE)
106
+ Log.log.debug { "Error with backtrace: #{message}" }
107
+ message = message.lines.grep_v(BACKTRACE_LINE).join.strip
108
+ end
100
109
  context[:messages].push(message)
101
110
  Log.log.trace1 { "Found error: #{type}: #{message}" }
102
111
  log_file = instance.log_file
@@ -120,19 +120,19 @@ module Aspera
120
120
  Aspera.assert_values(field, ['name']) { 'Default query field' }
121
121
  query = {'q'=> value}
122
122
  end
123
- lookup_entity_generic(entity: entity, field: field, value: value) { list_entities_limit_offset_total_count(entity: entity, items_key: items_key, query: query).first }
123
+ lookup_entity_generic(field: field, value: value, entity: entity) { list_entities_limit_offset_total_count(entity: entity, items_key: items_key, query: query).first }
124
124
  end
125
125
 
126
126
  # Lookup entity by field and value.
127
127
  # Extracts a single result from the list returned by the block.
128
128
  #
129
- # @param entity [String] Type of entity to lookup (path, and by default it is also the field name in result)
130
- # @param value [String] Value to match against the field.
131
- # @param field [String] Field to match in the hashes (defaults to 'name').
132
- # @yield [] A mandatory block that returns an Array of Hashes.
129
+ # @param field [String] Field to match in the hashes.
130
+ # @param value [String] Value to match against the field (exact match with `eql?`: case and type sensitive).
131
+ # @param entity [String] Type of entity to lookup (typically, API path, only used for exception)
132
+ # @yieldreturn [Array<Hash>] The list of entities to search (block is mandatory).
133
133
  # @return [Hash] The unique matching object.
134
134
  # @raise [Cli::BadIdentifier] If 0 or >1 matches are found.
135
- def lookup_entity_generic(entity:, value:, field: 'name')
135
+ def lookup_entity_generic(field:, value:, entity:)
136
136
  Aspera.assert(block_given?, 'block required for lookup_entity_generic')
137
137
  found = yield
138
138
  Aspera.assert_array_all(found, Hash)
@@ -3,6 +3,7 @@
3
3
  require 'aspera/rest/parameters'
4
4
  require 'aspera/log'
5
5
  require 'aspera/assert'
6
+ require 'aspera/secret_hider'
6
7
  require 'net/http'
7
8
  require 'net/https'
8
9
  require 'uri'
@@ -16,7 +17,12 @@ module Aspera
16
17
  # @param user [String] Username
17
18
  # @param pass [String] Password
18
19
  # @return [String] Basic auth token
19
- def basic_authorization(user, pass) = "Basic #{Base64.strict_encode64("#{user}:#{pass}")}"
20
+ def basic_authorization(user, pass)
21
+ credentials = Base64.strict_encode64("#{user}:#{pass}")
22
+ # Hidden wherever it appears (logs, results)
23
+ SecretHider.instance.add_secret_values(credentials)
24
+ "Basic #{credentials}"
25
+ end
20
26
 
21
27
  # Indicate that the given Hash query uses php style for array parameters
22
28
  # @param query [Hash] A key can have Array value and result will use PHP format: a[]=1&a[]=2
data/lib/aspera/rest.rb CHANGED
@@ -4,6 +4,5 @@ require 'aspera/rest/parameters'
4
4
  require 'aspera/rest/util'
5
5
  require 'aspera/rest/call_error'
6
6
  require 'aspera/rest/error_analyzer'
7
- require 'aspera/rest/aspera_errors'
8
7
  require 'aspera/rest/client'
9
8
  require 'aspera/rest/list'
@@ -32764,8 +32764,6 @@ components:
32764
32764
  type: string
32765
32765
  examples:
32766
32766
  - eyJyZXNvdXJjZSI6InBhY2thZ2VzIiwidHlwZSI6ImV4dGVybmFsX3ZpZXdfcGFja2FnZSIsImlkIjoiMzAiLCJwYXNzY29kZSI6IjA2MzBkZDIzLTA3YTAtNGExYi04N2IzLWM3YjZkMGViNjE5NiIsInBhY2thZ2VfaWQiOiIzMCJ9
32767
- maxLength: 255
32768
- minLength: 1
32769
32767
  relays_count:
32770
32768
  description: Package relays count
32771
32769
  type: object