aspera-cli 4.27.0 → 4.27.1

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 (140) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +29 -0
  4. data/CONTRIBUTING.md +1 -7
  5. data/TODO.md +50 -0
  6. data/docs/README.md +708 -488
  7. data/lib/aspera/agent/base.rb +10 -2
  8. data/lib/aspera/agent/connect.rb +7 -7
  9. data/lib/aspera/agent/desktop.rb +3 -3
  10. data/lib/aspera/agent/direct.rb +48 -19
  11. data/lib/aspera/agent/factory.rb +3 -3
  12. data/lib/aspera/agent/httpgw.rb +55 -14
  13. data/lib/aspera/agent/node.rb +2 -2
  14. data/lib/aspera/agent/transferd.rb +12 -12
  15. data/lib/aspera/api/aoc.rb +28 -28
  16. data/lib/aspera/api/cos_node.rb +10 -9
  17. data/lib/aspera/api/faspex.rb +2 -2
  18. data/lib/aspera/api/httpgw.rb +20 -20
  19. data/lib/aspera/api/node.rb +31 -53
  20. data/lib/aspera/ascmd.rb +13 -13
  21. data/lib/aspera/ascp/installation.rb +43 -36
  22. data/lib/aspera/ascp/management.rb +6 -6
  23. data/lib/aspera/assert.rb +12 -13
  24. data/lib/aspera/cli/ascp_actions.rb +7 -7
  25. data/lib/aspera/cli/async_transfer_store.rb +49 -5
  26. data/lib/aspera/cli/bootstrapper.rb +9 -9
  27. data/lib/aspera/cli/command_registry.rb +1 -1
  28. data/lib/aspera/cli/command_spec.rb +6 -3
  29. data/lib/aspera/cli/context.rb +3 -3
  30. data/lib/aspera/cli/extended_value.rb +26 -26
  31. data/lib/aspera/cli/formatter.rb +76 -54
  32. data/lib/aspera/cli/gem_checker.rb +1 -1
  33. data/lib/aspera/cli/hints.rb +2 -2
  34. data/lib/aspera/cli/http.rb +22 -29
  35. data/lib/aspera/cli/mailer.rb +7 -7
  36. data/lib/aspera/cli/mcp_tool.rb +31 -4
  37. data/lib/aspera/cli/option_declarator.rb +77 -0
  38. data/lib/aspera/cli/options.schema.yaml +273 -3
  39. data/lib/aspera/cli/parser.rb +539 -280
  40. data/lib/aspera/cli/plugins/alee.rb +1 -1
  41. data/lib/aspera/cli/plugins/aoc.rb +297 -313
  42. data/lib/aspera/cli/plugins/ats.rb +25 -21
  43. data/lib/aspera/cli/plugins/base.rb +357 -186
  44. data/lib/aspera/cli/plugins/basic_auth.rb +0 -12
  45. data/lib/aspera/cli/plugins/config.rb +76 -73
  46. data/lib/aspera/cli/plugins/console.rb +8 -8
  47. data/lib/aspera/cli/plugins/cos.rb +4 -3
  48. data/lib/aspera/cli/plugins/factory.rb +2 -2
  49. data/lib/aspera/cli/plugins/faspex5.rb +259 -248
  50. data/lib/aspera/cli/plugins/faspio.rb +7 -2
  51. data/lib/aspera/cli/plugins/httpgw.rb +1 -1
  52. data/lib/aspera/cli/plugins/mcp.rb +11 -11
  53. data/lib/aspera/cli/plugins/node.rb +227 -283
  54. data/lib/aspera/cli/plugins/orchestrator.rb +23 -23
  55. data/lib/aspera/cli/plugins/preview.rb +61 -64
  56. data/lib/aspera/cli/plugins/server.rb +36 -31
  57. data/lib/aspera/cli/plugins/shares.rb +174 -135
  58. data/lib/aspera/cli/preset_actions.rb +39 -19
  59. data/lib/aspera/cli/preset_manager.rb +74 -32
  60. data/lib/aspera/cli/result.rb +18 -16
  61. data/lib/aspera/cli/runner.rb +75 -39
  62. data/lib/aspera/cli/secret_finder.rb +1 -1
  63. data/lib/aspera/cli/sync_actions.rb +36 -35
  64. data/lib/aspera/cli/terminal_formatter.rb +2 -2
  65. data/lib/aspera/cli/transfer_actions.rb +17 -10
  66. data/lib/aspera/cli/transfer_agent.rb +44 -44
  67. data/lib/aspera/cli/transfer_progress.rb +7 -7
  68. data/lib/aspera/cli/vault_manager.rb +34 -12
  69. data/lib/aspera/cli/version.rb +1 -1
  70. data/lib/aspera/cli/wizard.rb +17 -20
  71. data/lib/aspera/colors.rb +3 -3
  72. data/lib/aspera/command_line_builder.rb +16 -16
  73. data/lib/aspera/command_line_converter.rb +1 -1
  74. data/lib/aspera/coverage.rb +1 -2
  75. data/lib/aspera/data_repository.rb +1 -1
  76. data/lib/aspera/dot_container.rb +8 -8
  77. data/lib/aspera/environment.rb +12 -12
  78. data/lib/aspera/faspex_gw.rb +4 -4
  79. data/lib/aspera/faspex_postproc.rb +14 -9
  80. data/lib/aspera/graphql.rb +4 -2
  81. data/lib/aspera/hash_ext.rb +2 -2
  82. data/lib/aspera/json_rpc/client.rb +1 -1
  83. data/lib/aspera/keychain/base.rb +10 -3
  84. data/lib/aspera/keychain/encrypted_hash.rb +92 -17
  85. data/lib/aspera/keychain/factory.rb +17 -5
  86. data/lib/aspera/keychain/hashicorp_vault.rb +1 -1
  87. data/lib/aspera/keychain/macos_security.rb +23 -25
  88. data/lib/aspera/keychain/one_password_api.rb +86 -0
  89. data/lib/aspera/keychain/one_password_base.rb +34 -0
  90. data/lib/aspera/keychain/one_password_cli.rb +98 -0
  91. data/lib/aspera/link_header.rb +2 -2
  92. data/lib/aspera/log.rb +13 -13
  93. data/lib/aspera/markdown.rb +5 -5
  94. data/lib/aspera/nagios.rb +8 -8
  95. data/lib/aspera/node_simulator.rb +33 -27
  96. data/lib/aspera/oauth/base.rb +4 -5
  97. data/lib/aspera/oauth/boot.rb +3 -3
  98. data/lib/aspera/oauth/factory.rb +5 -5
  99. data/lib/aspera/oauth/jwt.rb +5 -7
  100. data/lib/aspera/oauth/web.rb +4 -4
  101. data/lib/aspera/persistency_action_once.rb +4 -4
  102. data/lib/aspera/persistency_folder.rb +8 -8
  103. data/lib/aspera/preview/file_types.rb +4 -4
  104. data/lib/aspera/preview/generator.rb +49 -46
  105. data/lib/aspera/preview/options.rb +3 -2
  106. data/lib/aspera/preview/terminal.rb +5 -5
  107. data/lib/aspera/preview/utils.rb +65 -18
  108. data/lib/aspera/products/connect.rb +2 -2
  109. data/lib/aspera/products/desktop.rb +1 -1
  110. data/lib/aspera/products/other.rb +2 -2
  111. data/lib/aspera/products/transferd.rb +3 -3
  112. data/lib/aspera/proxy_auto_config.rb +10 -10
  113. data/lib/aspera/rest.rb +149 -115
  114. data/lib/aspera/rest_error_analyzer.rb +3 -3
  115. data/lib/aspera/rest_list.rb +10 -9
  116. data/lib/aspera/schema/IBM Aspera Node API-4.4.6.yaml +6232 -0
  117. data/lib/aspera/schema/IBM Aspera faspio Gateway API-1.0.0.yaml +249 -0
  118. data/lib/aspera/schema/IBM_Aspera_Shares.yaml +4653 -0
  119. data/lib/aspera/schema/documentation.rb +17 -11
  120. data/lib/aspera/schema/reader.rb +78 -4
  121. data/lib/aspera/schema/registry.rb +26 -7
  122. data/lib/aspera/secret_hider.rb +5 -5
  123. data/lib/aspera/ssh.rb +64 -31
  124. data/lib/aspera/ssl.rb +3 -3
  125. data/lib/aspera/sync/database.rb +2 -2
  126. data/lib/aspera/sync/operations.rb +13 -13
  127. data/lib/aspera/temp_file_manager.rb +24 -4
  128. data/lib/aspera/transfer/faux_file.rb +2 -2
  129. data/lib/aspera/transfer/parameters.rb +15 -15
  130. data/lib/aspera/transfer/resumer.rb +9 -9
  131. data/lib/aspera/transfer/spec.rb +1 -1
  132. data/lib/aspera/uri_reader.rb +52 -15
  133. data/lib/aspera/web_auth.rb +6 -5
  134. data/lib/aspera/web_server_simple.rb +9 -9
  135. data/lib/aspera/yaml.rb +4 -4
  136. data.tar.gz.sig +0 -0
  137. metadata +10 -4
  138. metadata.gz.sig +0 -0
  139. data/lib/aspera/cli/plugins/faspex.rb +0 -576
  140. data/lib/aspera/transfer/uri.rb +0 -56
@@ -27,12 +27,13 @@ module Aspera
27
27
  option :cloud, description: 'Cloud provider'
28
28
  option :region, description: 'Cloud region'
29
29
 
30
+ use_options Node
31
+
30
32
  def initialize(api: nil, **base_args)
31
33
  super(**base_args)
32
34
  @ats_api_open = Api::Ats.new
33
35
  @ats_api_auth = api
34
36
  options.parse_options!
35
- Node.declare_options(options)
36
37
  end
37
38
 
38
39
  # --- DSL ---
@@ -40,11 +41,11 @@ module Aspera
40
41
  command :cluster, description: 'Display general ATS cluster information (public API, no auth)'
41
42
  command :access_key, description: 'Manage ATS access keys'
42
43
  command :api_key, description: 'Manage credential to access ATS API', condition: :api_key_available?
43
- command :aws_trust_policy, description: 'Show AWS trust policy', action: lambda{Result::SingleObject.new(ats_api.read('aws/trustpolicy', {region: options.get_option(:region, mandatory: true)}))}
44
+ command :aws_trust_policy, description: 'Show AWS trust policy', action: lambda { Result::SingleObject.new(ats_api.read('aws/trustpolicy', {region: options.get_option(:region, mandatory: true)})) }
44
45
 
45
46
  commands_under(:cluster) do
46
- command :clouds, description: 'List cloud providers', action: lambda{Result::ObjectList.new(@ats_api_open.cloud_names.map{ |k, v| CLOUD_TABLE.zip([k, v]).to_h})}
47
- command :list, description: 'List ATS servers', action: lambda{Result::ObjectList.new(@ats_api_open.all_servers, fields: %w[id cloud region])}
47
+ command :clouds, description: 'List cloud providers', action: lambda { Result::ObjectList.new(@ats_api_open.cloud_names.map { |k, v| CLOUD_TABLE.zip([k, v]).to_h }) }
48
+ command :list, description: 'List ATS servers', action: lambda { Result::ObjectList.new(@ats_api_open.all_servers, fields: %w[id cloud region]) }
48
49
  command :show, description: 'Show a specific server'
49
50
  end
50
51
 
@@ -57,7 +58,7 @@ module Aspera
57
58
  end)
58
59
  command :show, description: 'Show an access key',
59
60
  arguments: [{name: :access_key_id, type: :identifier}],
60
- action: ->(access_key_id:, **){Result::SingleObject.new(ats_api.read("access_keys/#{access_key_id}"))}
61
+ action: ->(access_key_id:, **) { Result::SingleObject.new(ats_api.read("access_keys/#{access_key_id}")) }
61
62
  command :modify, description: 'Modify an access key',
62
63
  arguments: [{name: :access_key_id, type: :identifier}, {name: :params, type: Hash}]
63
64
  command :delete, description: 'Delete an access key',
@@ -71,25 +72,27 @@ module Aspera
71
72
  arguments: [{name: :access_key_id, type: :identifier}]
72
73
  end
73
74
 
74
- commands_under(%i[access_key node]) do
75
- Node::COMMANDS_GEN4.each do |cmd|
76
- command(cmd, description: "Node Gen4 #{cmd} command")
75
+ commands_under %i[access_key node] do
76
+ command :permission, description: 'Manage permissions'
77
+ command :sync, description: 'Synchronize folders'
78
+ Node::COMMANDS_GEN4_SPEC.each do |cmd, spec|
79
+ command cmd, **spec
77
80
  end
78
81
  end
79
82
 
80
83
  commands_under(:api_key) do
81
84
  command(:instances, description: 'List ATS instances in IBM Cloud', action: lambda do
82
85
  instances = ats_api_v2_auth_ibm.read('instances')
83
- Log.log.warn{"more instances remaining: #{instances['remaining']}"} unless instances['remaining'].to_i.eql?(0)
86
+ Log.log.warn { "more instances remaining: #{instances['remaining']}" } unless instances['remaining'].to_i.eql?(0)
84
87
  Result::ValueList.new(instances['data'], name: 'instance')
85
88
  end)
86
89
  command :create, description: 'Create an ATS API key',
87
90
  arguments: [{name: :params, type: Hash, mandatory: false, default: {}}],
88
- action: ->(params:, **){Result::SingleObject.new(build_ats_ibm_api_with_instance.create('api_keys', params))}
89
- command :list, description: 'List ATS API keys', action: lambda{Result::ValueList.new(build_ats_ibm_api_with_instance.read('api_keys', {'offset' => 0, 'max_results' => 1000})['data'], name: 'ats_id')}
91
+ action: ->(params:, **) { Result::SingleObject.new(build_ats_ibm_api_with_instance.create('api_keys', params)) }
92
+ command :list, description: 'List ATS API keys', action: lambda { Result::ValueList.new(build_ats_ibm_api_with_instance.read('api_keys', {'offset' => 0, 'max_results' => 1000})['data'], name: 'ats_id') }
90
93
  command :show, description: 'Show an ATS API key',
91
94
  arguments: [{name: :api_key_id, type: :identifier}],
92
- action: ->(api_key_id:, **){Result::SingleObject.new(build_ats_ibm_api_with_instance.read("api_keys/#{api_key_id}"))}
95
+ action: ->(api_key_id:, **) { Result::SingleObject.new(build_ats_ibm_api_with_instance.read("api_keys/#{api_key_id}")) }
93
96
  command :delete, description: 'Delete an ATS API key',
94
97
  arguments: [{name: :api_key_id, type: :identifier}]
95
98
  end
@@ -146,7 +149,7 @@ module Aspera
146
149
  server_data = server_by_cloud_region
147
150
  else
148
151
  server_id = options.instance_identifier
149
- server_data = @ats_api_open.all_servers.find{ |i| i['id'].eql?(server_id)}
152
+ server_data = @ats_api_open.all_servers.find { |i| i['id'].eql?(server_id) }
150
153
  raise BadIdentifier.new('server', server_id) if server_data.nil?
151
154
  end
152
155
  Result::SingleObject.new(server_data)
@@ -159,14 +162,14 @@ module Aspera
159
162
  server_data = server_by_cloud_region
160
163
  params['transfer_server_id'] = server_data['id']
161
164
  end
162
- Log.log.debug{"using params: #{params}".bg_red.gray}
165
+ Log.log.debug { "using params: #{params}".bg_red.gray }
163
166
  if params.key?('storage')
164
167
  case params['storage']['type']
165
168
  # here we need somehow to map storage type to field to get for auth end point
166
169
  when 'ibm-s3'
167
170
  server_data2 = nil
168
171
  if server_data.nil?
169
- server_data2 = @ats_api_open.all_servers.find{ |s| s['id'].eql?(params['transfer_server_id'])}
172
+ server_data2 = @ats_api_open.all_servers.find { |s| s['id'].eql?(params['transfer_server_id']) }
170
173
  raise "no such transfer server id: #{params['transfer_server_id']}" if server_data2.nil?
171
174
  else
172
175
  server_data2 = @ats_api_open.all_servers.find do |s|
@@ -208,8 +211,8 @@ module Aspera
208
211
  # @return [Hash] context hash containing :ak_node_plugin and :ak_root_file_id
209
212
  def setup_ak_node(access_key_id:, **)
210
213
  ak_data = ats_api.read("access_keys/#{access_key_id}")
211
- server_data = @ats_api_open.all_servers.find{ |i| i['id'].start_with?(ak_data['transfer_server_id'])}
212
- Aspera.assert(!server_data.nil?, type: Cli::Error){'no such server found'}
214
+ server_data = @ats_api_open.all_servers.find { |i| i['id'].start_with?(ak_data['transfer_server_id']) }
215
+ Aspera.assert(!server_data.nil?, type: Cli::Error) { 'no such server found' }
213
216
  node_url = server_data['transfer_setup_url']
214
217
  api_node = Api::Node.new(
215
218
  base_url: node_url,
@@ -226,18 +229,19 @@ module Aspera
226
229
  end
227
230
 
228
231
  # One handler per COMMANDS_GEN4 - delegates to the Node plugin's DSL registry.
232
+ # Pre-resolved arguments (e.g. path:) are forwarded via **ctx to avoid double token consumption.
229
233
  Node::COMMANDS_GEN4.each do |cmd|
230
- define_action_method([:access_key, :node, cmd]) do |ak_node_plugin:, ak_root_file_id:, **|
234
+ define_action_method([:access_key, :node, cmd]) do |ak_node_plugin:, ak_root_file_id:, **ctx|
231
235
  # For permission: the handler consumes the path first then re-dispatches to sub-commands.
232
236
  # Calling dispatch_from_registry with skip_setup would bypass path consumption and fail.
233
- next ak_node_plugin.send(:"action_access_keys_do_#{cmd}", do_root_file_id: ak_root_file_id) if cmd.eql?(:permission)
234
- ak_node_plugin.dispatch_from_registry([:access_keys, :do, cmd], {do_root_file_id: ak_root_file_id}, skip_setup: true)
237
+ next ak_node_plugin.send(:"action_access_keys_do_#{cmd}", do_root_file_id: ak_root_file_id, **ctx) if cmd.eql?(:permission)
238
+ ak_node_plugin.dispatch_from_registry([:access_keys, :do, cmd], {do_root_file_id: ak_root_file_id, **ctx}, skip_setup: true)
235
239
  end
236
240
  end
237
241
 
238
242
  def action_api_key_instances
239
243
  instances = ats_api_v2_auth_ibm.read('instances')
240
- Log.log.warn{"more instances remaining: #{instances['remaining']}"} unless instances['remaining'].to_i.eql?(0)
244
+ Log.log.warn { "more instances remaining: #{instances['remaining']}" } unless instances['remaining'].to_i.eql?(0)
241
245
  Result::ValueList.new(instances['data'], name: 'instance')
242
246
  end
243
247