aspera-cli 4.26.2 → 4.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +281 -21
- data/CONTRIBUTING.md +98 -7
- data/bin/ascli +3 -3
- data/docs/README.md +10757 -0
- data/docs/test-mcp-with-ai.md +202 -0
- data/lib/aspera/agent/base.rb +20 -6
- data/lib/aspera/agent/connect.rb +53 -16
- data/lib/aspera/agent/desktop.rb +52 -17
- data/lib/aspera/agent/direct.rb +26 -24
- data/lib/aspera/agent/httpgw.rb +1 -1
- data/lib/aspera/agent/node.rb +32 -0
- data/lib/aspera/agent/transferd.rb +39 -3
- data/lib/aspera/api/alee.rb +1 -1
- data/lib/aspera/api/aoc.rb +14 -16
- data/lib/aspera/api/cos_node.rb +1 -1
- data/lib/aspera/api/faspex.rb +15 -14
- data/lib/aspera/api/httpgw.rb +4 -4
- data/lib/aspera/api/node.rb +26 -23
- data/lib/aspera/api/queries/bss_subscription_account.graphql +18 -0
- data/lib/aspera/api/queries/bss_subscription_usage.graphql +18 -0
- data/lib/aspera/ascmd.rb +21 -19
- data/lib/aspera/ascp/installation.rb +37 -38
- data/lib/aspera/ascp/management.rb +2 -3
- data/lib/aspera/cli/ascp_actions.rb +155 -0
- data/lib/aspera/cli/async_transfer_store.rb +81 -0
- data/lib/aspera/cli/bootstrapper.rb +197 -0
- data/lib/aspera/cli/command_registry.rb +145 -0
- data/lib/aspera/cli/command_spec.rb +138 -0
- data/lib/aspera/cli/context.rb +16 -3
- data/lib/aspera/cli/error.rb +16 -0
- data/lib/aspera/cli/extended_value.rb +2 -1
- data/lib/aspera/cli/formatter.rb +41 -27
- data/lib/aspera/cli/gem_checker.rb +65 -0
- data/lib/aspera/cli/hints.rb +2 -2
- data/lib/aspera/cli/http.rb +70 -19
- data/lib/aspera/cli/info.rb +2 -0
- data/lib/aspera/cli/mailer.rb +97 -0
- data/lib/aspera/cli/mcp_tool.rb +198 -0
- data/lib/aspera/cli/options.schema.yaml +364 -7
- data/lib/aspera/cli/{manager.rb → parser.rb} +334 -142
- data/lib/aspera/cli/plugins/alee.rb +20 -22
- data/lib/aspera/cli/plugins/aoc.rb +1166 -853
- data/lib/aspera/cli/plugins/ats.rb +200 -161
- data/lib/aspera/cli/plugins/base.rb +457 -100
- data/lib/aspera/cli/plugins/basic_auth.rb +14 -4
- data/lib/aspera/cli/plugins/config.rb +428 -754
- data/lib/aspera/cli/plugins/console.rb +106 -64
- data/lib/aspera/cli/plugins/cos.rb +44 -32
- data/lib/aspera/cli/plugins/factory.rb +4 -4
- data/lib/aspera/cli/plugins/faspex.rb +294 -257
- data/lib/aspera/cli/plugins/faspex5.rb +585 -357
- data/lib/aspera/cli/plugins/faspio.rb +49 -51
- data/lib/aspera/cli/plugins/httpgw.rb +18 -25
- data/lib/aspera/cli/plugins/mcp.rb +279 -0
- data/lib/aspera/cli/plugins/node.rb +998 -794
- data/lib/aspera/cli/plugins/oauth.rb +7 -10
- data/lib/aspera/cli/plugins/orchestrator.rb +111 -134
- data/lib/aspera/cli/plugins/preview.rb +180 -139
- data/lib/aspera/cli/plugins/server.rb +124 -79
- data/lib/aspera/cli/plugins/shares.rb +301 -107
- data/lib/aspera/cli/preset_actions.rb +139 -0
- data/lib/aspera/cli/preset_manager.rb +13 -12
- data/lib/aspera/cli/result.rb +61 -11
- data/lib/aspera/cli/runner.rb +275 -141
- data/lib/aspera/cli/secret_finder.rb +40 -0
- data/lib/aspera/cli/special_values.rb +1 -0
- data/lib/aspera/cli/sync_actions.rb +83 -59
- data/lib/aspera/cli/terminal_formatter.rb +1 -1
- data/lib/aspera/cli/transfer_actions.rb +83 -0
- data/lib/aspera/cli/transfer_agent.rb +116 -51
- data/lib/aspera/cli/transfer_progress.rb +3 -3
- data/lib/aspera/cli/vault_manager.rb +57 -0
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +21 -20
- data/lib/aspera/command_line_builder.rb +22 -22
- data/lib/aspera/data_repository.rb +2 -1
- data/lib/aspera/dot_container.rb +4 -4
- data/lib/aspera/environment.rb +18 -11
- data/lib/aspera/exec_spec.rb +13 -0
- data/lib/aspera/faspex_gw.rb +1 -1
- data/lib/aspera/faspex_postproc.rb +4 -3
- data/lib/aspera/graphql.rb +35 -0
- data/lib/aspera/hash_ext.rb +6 -0
- data/lib/aspera/json_rpc/client.rb +62 -0
- data/lib/aspera/json_rpc/version.rb +7 -0
- data/lib/aspera/keychain/encrypted_hash.rb +1 -1
- data/lib/aspera/keychain/factory.rb +3 -3
- data/lib/aspera/keychain/macos_security.rb +3 -3
- data/lib/aspera/link_header.rb +82 -0
- data/lib/aspera/log.rb +17 -3
- data/lib/aspera/markdown.rb +85 -2
- data/lib/aspera/node_simulator.rb +3 -1
- data/lib/aspera/oauth/base.rb +5 -5
- data/lib/aspera/oauth/boot.rb +2 -2
- data/lib/aspera/oauth/factory.rb +7 -5
- data/lib/aspera/oauth/jwt.rb +4 -4
- data/lib/aspera/oauth/web.rb +2 -2
- data/lib/aspera/persistency_action_once.rb +8 -8
- data/lib/aspera/persistency_folder.rb +10 -3
- data/lib/aspera/preview/file_types.rb +3 -3
- data/lib/aspera/preview/generator.rb +3 -3
- data/lib/aspera/preview/utils.rb +1 -1
- data/lib/aspera/products/connect.rb +1 -1
- data/lib/aspera/products/other.rb +1 -1
- data/lib/aspera/products/transferd.rb +1 -1
- data/lib/aspera/proxy_auto_config.rb +7 -6
- data/lib/aspera/rest.rb +10 -36
- data/lib/aspera/rest_error_analyzer.rb +3 -3
- data/lib/aspera/rest_errors_aspera.rb +0 -10
- data/lib/aspera/rest_list.rb +3 -3
- data/lib/aspera/schema/IBM Aspera on Cloud API-0.2.6-enhanced.yaml +1853 -510
- data/lib/aspera/schema/documentation.rb +57 -26
- data/lib/aspera/schema/reader.rb +59 -10
- data/lib/aspera/schema/registry.rb +39 -6
- data/lib/aspera/secret_hider.rb +7 -2
- data/lib/aspera/ssl.rb +4 -4
- data/lib/aspera/sync/conf.schema.yaml +2 -2
- data/lib/aspera/sync/operations.rb +10 -13
- data/lib/aspera/temp_file_manager.rb +1 -1
- data/lib/aspera/timer_limiter.rb +1 -1
- data/lib/aspera/transfer/faux_file.rb +24 -11
- data/lib/aspera/transfer/parameters.rb +23 -21
- data/lib/aspera/transfer/result.rb +74 -0
- data/lib/aspera/transfer/resumer.rb +6 -6
- data/lib/aspera/transfer/spec.rb +18 -1
- data/lib/aspera/transfer/spec.schema.yaml +12 -3
- data/lib/aspera/uri_reader.rb +2 -2
- data/lib/aspera/web_auth.rb +2 -2
- data/lib/aspera/web_server_simple.rb +8 -5
- data/lib/aspera/yaml.rb +2 -1
- data.tar.gz.sig +0 -0
- metadata +25 -3
- metadata.gz.sig +0 -0
- data/lib/aspera/json_rpc.rb +0 -52
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'aspera/log'
|
|
4
4
|
require 'aspera/assert'
|
|
5
|
+
require 'aspera/exec_spec'
|
|
5
6
|
require 'aspera/command_line_builder'
|
|
6
7
|
require 'aspera/temp_file_manager'
|
|
7
8
|
require 'aspera/transfer/error'
|
|
@@ -38,8 +39,9 @@ module Aspera
|
|
|
38
39
|
@file_list_folder ||= TempFileManager.instance.new_file_path_global('asession_filelists')
|
|
39
40
|
end
|
|
40
41
|
|
|
41
|
-
#
|
|
42
|
-
# @
|
|
42
|
+
# Check whether a file list option is already present in the `ascp` argument list
|
|
43
|
+
# @param ascp_args [Array, nil] `ascp` arguments
|
|
44
|
+
# @return [Boolean] true if a file list option is present
|
|
43
45
|
def ascp_args_file_list?(ascp_args)
|
|
44
46
|
ascp_args&.any?{ |i| FILE_LIST_OPTIONS.include?(i)}
|
|
45
47
|
end
|
|
@@ -47,7 +49,9 @@ module Aspera
|
|
|
47
49
|
|
|
48
50
|
# @param job_spec [Hash] Transfer specification
|
|
49
51
|
# @param ascp_args [Array] Other `ascp` args
|
|
52
|
+
# @param wss [Boolean] `true`: if both SSH and wss in ts: prefer wss
|
|
50
53
|
# @param quiet [Boolean] Remove `ascp` progress bar if `true`
|
|
54
|
+
# @param file_list [Boolean] `true`: provide source list via a temp file, `false`: place directly on command line
|
|
51
55
|
# @param client_ssh_key [:rsa,:dsa] Type of Aspera Client SSH key to use.
|
|
52
56
|
# @param trusted_certs [Array<String>] List of path to trusted certificates stores when using WSS
|
|
53
57
|
# @param check_ignore_cb [Proc] Callback to check if WSS connection shall ignore certificate validity
|
|
@@ -56,6 +60,7 @@ module Aspera
|
|
|
56
60
|
ascp_args: nil,
|
|
57
61
|
wss: true,
|
|
58
62
|
quiet: true,
|
|
63
|
+
file_list: true,
|
|
59
64
|
trusted_certs: nil,
|
|
60
65
|
client_ssh_key: nil,
|
|
61
66
|
check_ignore_cb: nil
|
|
@@ -66,6 +71,7 @@ module Aspera
|
|
|
66
71
|
Aspera.assert_array_all(@ascp_args, String){'ascp_args'}
|
|
67
72
|
@wss = wss
|
|
68
73
|
@quiet = quiet
|
|
74
|
+
@file_list = file_list
|
|
69
75
|
@trusted_certs = trusted_certs.nil? ? [] : trusted_certs
|
|
70
76
|
Aspera.assert_type(@trusted_certs, Array){'trusted_certs'}
|
|
71
77
|
@client_ssh_key = client_ssh_key.nil? ? :rsa : client_ssh_key.to_sym
|
|
@@ -74,7 +80,7 @@ module Aspera
|
|
|
74
80
|
@builder = CommandLineBuilder.new(@job_spec, Spec::SCHEMA, CommandLineConverter)
|
|
75
81
|
end
|
|
76
82
|
|
|
77
|
-
#
|
|
83
|
+
# Place source files on command line or in a temp file list, controlled by @file_list and file_list_folder
|
|
78
84
|
def process_file_list
|
|
79
85
|
# is the file list provided through ascp parameters?
|
|
80
86
|
ascp_file_list_provided = self.class.ascp_args_file_list?(@ascp_args)
|
|
@@ -88,8 +94,8 @@ module Aspera
|
|
|
88
94
|
Aspera.assert(!ascp_file_list_provided, 'file list provided both in transfer spec and ascp file list. Remove one of them.')
|
|
89
95
|
Aspera.assert(ts_paths_array.all?{ |i| i.key?('source')}, "All elements of paths must have a 'source' key")
|
|
90
96
|
is_pair_list = ts_paths_array.any?{ |i| i.key?('destination')}
|
|
91
|
-
|
|
92
|
-
if self.class.file_list_folder.nil?
|
|
97
|
+
Aspera.assert(!(is_pair_list && !ts_paths_array.all?{ |i| i.key?('destination')})){"All elements of paths must be consistent with 'destination' key"}
|
|
98
|
+
if !@file_list || self.class.file_list_folder.nil?
|
|
93
99
|
Aspera.assert(!is_pair_list, 'file pair list is not supported when file list folder is not set')
|
|
94
100
|
# not safe for special characters ? (maybe not, depends on OS)
|
|
95
101
|
Log.log.debug('placing source file list on command line (no file list file)')
|
|
@@ -112,7 +118,7 @@ module Aspera
|
|
|
112
118
|
@builder.add_command_line_options("#{file_list_option}=#{file_list_file}") unless file_list_option.nil?
|
|
113
119
|
end
|
|
114
120
|
|
|
115
|
-
# @return the list of certificates (option `-i`) to use when token/ssh or wss are used
|
|
121
|
+
# @return [Array<String>] the list of certificates (option `-i`) to use when token/ssh or wss are used
|
|
116
122
|
def remote_certificates
|
|
117
123
|
certificates_to_use = []
|
|
118
124
|
# use web socket secure for session ?
|
|
@@ -150,11 +156,7 @@ module Aspera
|
|
|
150
156
|
|
|
151
157
|
# Translate transfer spec to env vars and command line arguments for `ascp`
|
|
152
158
|
def ascp_args
|
|
153
|
-
|
|
154
|
-
args: [],
|
|
155
|
-
env: {},
|
|
156
|
-
name: :ascp
|
|
157
|
-
}
|
|
159
|
+
exec_spec = Aspera::ExecSpec.new(exec: :ascp)
|
|
158
160
|
|
|
159
161
|
# Special cases
|
|
160
162
|
@job_spec.delete('source_root') if @job_spec.key?('source_root') && @job_spec['source_root'].empty?
|
|
@@ -165,7 +167,7 @@ module Aspera
|
|
|
165
167
|
# Add ssh or wss certificates
|
|
166
168
|
# (reverse, to keep order, as we unshift)
|
|
167
169
|
remote_certificates&.reverse_each do |cert|
|
|
168
|
-
|
|
170
|
+
exec_spec.args.unshift('-i', cert)
|
|
169
171
|
end
|
|
170
172
|
|
|
171
173
|
case (delete_source = @builder.read_param('delete_source'))
|
|
@@ -183,9 +185,9 @@ module Aspera
|
|
|
183
185
|
base64_destination = false
|
|
184
186
|
# symbol must be index of Ascp::Installation.paths
|
|
185
187
|
if @builder.read_param('use_ascp4')
|
|
186
|
-
|
|
188
|
+
exec_spec.exec = :ascp4
|
|
187
189
|
else
|
|
188
|
-
|
|
190
|
+
exec_spec.exec = :ascp
|
|
189
191
|
base64_destination = true
|
|
190
192
|
end
|
|
191
193
|
# destination will be base64 encoded, put this before source path arguments
|
|
@@ -200,17 +202,17 @@ module Aspera
|
|
|
200
202
|
destination_folder = Base64.strict_encode64(destination_folder) if base64_destination
|
|
201
203
|
# destination MUST be last command line argument to ascp
|
|
202
204
|
@builder.add_command_line_options(destination_folder)
|
|
203
|
-
@builder.
|
|
204
|
-
|
|
205
|
+
@builder.add_to_exec_spec(exec_spec)
|
|
206
|
+
exec_spec.args.unshift('-q') if @quiet
|
|
205
207
|
# add fallback cert and key as arguments if needed
|
|
206
208
|
if HTTP_FALLBACK_ACTIVATION_VALUES.include?(@job_spec['http_fallback'])
|
|
207
|
-
|
|
208
|
-
|
|
209
|
+
exec_spec.args.unshift('-Y', Ascp::Installation.instance.path(:fallback_private_key))
|
|
210
|
+
exec_spec.args.unshift('-I', Ascp::Installation.instance.path(:fallback_certificate))
|
|
209
211
|
end
|
|
210
212
|
# disable redis in client, only for ascp, this makes ascp4 fail
|
|
211
|
-
|
|
212
|
-
Log.log.debug{"ascp args: #{
|
|
213
|
-
return
|
|
213
|
+
exec_spec.env['ASPERA_TEST_REDIS_DISABLE'] = 'true' if exec_spec.exec.eql?(:ascp)
|
|
214
|
+
Log.log.debug{"ascp args: #{exec_spec}"}
|
|
215
|
+
return exec_spec
|
|
214
216
|
end
|
|
215
217
|
DELETE_EQUIV = %w[remove_after_transfer remove_empty_directories remove_empty_source_directory]
|
|
216
218
|
# `ascp` options to provide a file list
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Aspera
|
|
4
|
+
module Transfer
|
|
5
|
+
# Typed result of a transfer operation.
|
|
6
|
+
# Replaces the ad-hoc Array polymorphism previously returned by agents.
|
|
7
|
+
#
|
|
8
|
+
# Agents return one of the three concrete sub-classes:
|
|
9
|
+
# Transfer::Result::Success — all sessions completed successfully
|
|
10
|
+
# Transfer::Result::Error — at least one session failed
|
|
11
|
+
# Transfer::Result::Async — transfer submitted to a daemon; not yet complete
|
|
12
|
+
class Result
|
|
13
|
+
# All sessions completed successfully.
|
|
14
|
+
class Success < Result
|
|
15
|
+
def to_s
|
|
16
|
+
'success'
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# At least one session failed.
|
|
21
|
+
class Error < Result
|
|
22
|
+
# @return [StandardError]
|
|
23
|
+
attr_reader :exception
|
|
24
|
+
|
|
25
|
+
def initialize(exception)
|
|
26
|
+
super()
|
|
27
|
+
@exception = exception
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_s
|
|
31
|
+
"error: #{@exception.message}"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Transfer submitted to an external daemon; status not yet known.
|
|
36
|
+
class Async < Result
|
|
37
|
+
# @return [String] UUID assigned to this background job
|
|
38
|
+
attr_reader :job_id
|
|
39
|
+
# @return [String] initial status string (e.g. 'running')
|
|
40
|
+
attr_reader :status
|
|
41
|
+
|
|
42
|
+
def initialize(job_id:, status: 'running')
|
|
43
|
+
super()
|
|
44
|
+
@job_id = job_id
|
|
45
|
+
@status = status
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Convenience: export as a plain Hash for serialization / display
|
|
49
|
+
def to_h
|
|
50
|
+
{'job_id' => @job_id, 'status' => @status}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def to_s
|
|
54
|
+
"async job_id=#{@job_id} status=#{@status}"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Factory helpers
|
|
59
|
+
class << self
|
|
60
|
+
def success
|
|
61
|
+
Success.new
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def error(exception)
|
|
65
|
+
Error.new(exception)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def async(job_id:, status: 'running')
|
|
69
|
+
Async.new(job_id: job_id, status: status)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -12,20 +12,20 @@ module Aspera
|
|
|
12
12
|
# @param iter_max [Integer] Maximum number of executions
|
|
13
13
|
# @param sleep_initial [Integer] Initial wait to re-execute
|
|
14
14
|
# @param sleep_factor [Integer] Multiplier
|
|
15
|
-
# @param sleep_max
|
|
15
|
+
# @param sleep_max [Integer] Max iterations
|
|
16
16
|
def initialize(
|
|
17
17
|
iter_max: 7,
|
|
18
18
|
sleep_initial: 2,
|
|
19
19
|
sleep_factor: 2,
|
|
20
20
|
sleep_max: 60
|
|
21
21
|
)
|
|
22
|
-
Aspera.assert_type(iter_max, Integer){
|
|
22
|
+
Aspera.assert_type(iter_max, Integer){'iter_max'}
|
|
23
23
|
@iter_max = iter_max
|
|
24
|
-
Aspera.assert_type(sleep_initial, Integer){
|
|
24
|
+
Aspera.assert_type(sleep_initial, Integer){'sleep_initial'}
|
|
25
25
|
@sleep_initial = sleep_initial
|
|
26
|
-
Aspera.assert_type(sleep_factor, Integer){
|
|
26
|
+
Aspera.assert_type(sleep_factor, Integer){'sleep_factor'}
|
|
27
27
|
@sleep_factor = sleep_factor
|
|
28
|
-
Aspera.assert_type(sleep_max, Integer){
|
|
28
|
+
Aspera.assert_type(sleep_max, Integer){'sleep_max'}
|
|
29
29
|
@sleep_max = sleep_max
|
|
30
30
|
end
|
|
31
31
|
|
|
@@ -53,7 +53,7 @@ module Aspera
|
|
|
53
53
|
# do not retry non-retryable
|
|
54
54
|
raise unless e.retryable?
|
|
55
55
|
# exit if we exceed the max number of retry
|
|
56
|
-
|
|
56
|
+
Aspera.assert(remaining_resumes > 0, type: Error){"Maximum number of retry reached: #{@iter_max}"}
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
# take this retry in account
|
data/lib/aspera/transfer/spec.rb
CHANGED
|
@@ -34,7 +34,13 @@ module Aspera
|
|
|
34
34
|
'sparse_csum' => 'sparse_checksum',
|
|
35
35
|
'full_csum' => 'full_checksum'
|
|
36
36
|
}
|
|
37
|
-
|
|
37
|
+
# Multipliers for target_rate suffix (result is in kbps)
|
|
38
|
+
RATE_SUFFIX_KBPS = {
|
|
39
|
+
'k' => 1,
|
|
40
|
+
'm' => 1_000,
|
|
41
|
+
'g' => 1_000_000
|
|
42
|
+
}.freeze
|
|
43
|
+
private_constant :POLICY_FIX, :RATE_SUFFIX_KBPS
|
|
38
44
|
# translate upload/download to send/receive
|
|
39
45
|
def transfer_type_to_direction(transfer_type)
|
|
40
46
|
XFER_TYPE_TO_DIR.fetch(transfer_type)
|
|
@@ -45,6 +51,17 @@ module Aspera
|
|
|
45
51
|
XFER_DIR_TO_TYPE.fetch(direction)
|
|
46
52
|
end
|
|
47
53
|
|
|
54
|
+
# Parse a human-readable rate string (as accepted by ascp -l) into an integer kbps value.
|
|
55
|
+
# Accepted: plain integer (kbps), or integer + suffix k/K (kbps), m/M (x1000 kbps), g/G (x1000000 kbps).
|
|
56
|
+
# @param value [String] e.g. "100m", "500000", "1g"
|
|
57
|
+
# @return [Integer] value in kbps
|
|
58
|
+
def rate_string_to_kbps(value)
|
|
59
|
+
m = value.to_s.strip.match(/\A(\d+)([kKmMgG])?\z/)
|
|
60
|
+
Aspera.assert(m){"Invalid rate value: #{value.inspect}. Expected integer with optional suffix k/K, m/M or g/G."}
|
|
61
|
+
multiplier = m[2] ? RATE_SUFFIX_KBPS.fetch(m[2].downcase) : 1
|
|
62
|
+
return m[1].to_i * multiplier
|
|
63
|
+
end
|
|
64
|
+
|
|
48
65
|
def fix_transferd_resume_policy(transfer_spec)
|
|
49
66
|
# Fix discrepancy in transfer spec
|
|
50
67
|
transfer_spec['resume_policy'] = POLICY_FIX[transfer_spec['resume_policy']] if transfer_spec.key?('resume_policy')
|
|
@@ -377,6 +377,7 @@ properties:
|
|
|
377
377
|
description: Specifies whether to precalculate the job size.
|
|
378
378
|
type: boolean
|
|
379
379
|
x-cli-switch: true
|
|
380
|
+
x-cli-false: --precalculate-disable
|
|
380
381
|
preserve_access_time:
|
|
381
382
|
description: >-
|
|
382
383
|
Preserve the source-file access timestamps at the destination.
|
|
@@ -711,11 +712,11 @@ properties:
|
|
|
711
712
|
Refer to HSTS manual for more details.
|
|
712
713
|
|
|
713
714
|
- `follow`: Follow a symbolic link and transfer the contents of the linked file or directory when the link target is in the user's docroot.
|
|
714
|
-
|
|
715
|
+
|
|
715
716
|
- `copy`: Copy only the symbolic link. If a file with the same name exists at the destination, the symbolic link does not replace the file.
|
|
716
|
-
|
|
717
|
+
|
|
717
718
|
- `skip`: Skip-symbolic links. The link or the file to which it points are not transferred.
|
|
718
|
-
|
|
719
|
+
|
|
719
720
|
- `copy+force`: Copy only the symbolic link. If a file with the same name exists at the destination, the symbolic link replaces the file. If the file of the same name at the destination is a symbolic link to a directory, it is not replaced.
|
|
720
721
|
type: string
|
|
721
722
|
enum:
|
|
@@ -753,6 +754,14 @@ properties:
|
|
|
753
754
|
description: Specifies desired speed for the transfer.
|
|
754
755
|
type: integer
|
|
755
756
|
x-cli-option: -l
|
|
757
|
+
target_rate:
|
|
758
|
+
description: >-
|
|
759
|
+
Pseudo-parameter: desired transfer rate as a human-readable string with an optional unit suffix.
|
|
760
|
+
Converted to `target_rate_kbps` before the transfer is started, overriding it if both are present.
|
|
761
|
+
Accepted formats: plain integer (kbps), or integer followed by `k`/`K` (kbps), `m`/`M` (x1000 kbps), `g`/`G` (x1000000 kbps).
|
|
762
|
+
Examples: `100000`, `100000k`, `100m`, `1g`.
|
|
763
|
+
type: string
|
|
764
|
+
x-cli-special: true
|
|
756
765
|
title:
|
|
757
766
|
description: Title of the transfer.
|
|
758
767
|
type: string
|
data/lib/aspera/uri_reader.rb
CHANGED
|
@@ -45,14 +45,14 @@ module Aspera
|
|
|
45
45
|
end
|
|
46
46
|
when SCHEME_FILE, NilClass
|
|
47
47
|
local_file_path = uri.path
|
|
48
|
-
|
|
48
|
+
Aspera.assert(!local_file_path.nil?, type: Error){'URL shall have a path, check syntax'}
|
|
49
49
|
local_file_path = File.expand_path(local_file_path.gsub(%r{^/}, '')) if %r{^/(~|.|..)/}.match?(local_file_path)
|
|
50
50
|
return File.read(local_file_path)
|
|
51
51
|
else Aspera.error_unexpected_value(uri.scheme){"scheme for [#{uri_to_read}]"}
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
# @return
|
|
55
|
+
# @return [String] path to file with content at URL
|
|
56
56
|
def read_as_file(url)
|
|
57
57
|
if url.start_with?(SCHEME_FILE_PFX1)
|
|
58
58
|
# for file scheme, return directly the path
|
data/lib/aspera/web_auth.rb
CHANGED
|
@@ -6,8 +6,8 @@ require 'aspera/assert'
|
|
|
6
6
|
module Aspera
|
|
7
7
|
# servlet called on callback: it records the callback request
|
|
8
8
|
class WebAuthServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
9
|
-
# @param server
|
|
10
|
-
# @param web_auth [WebAuth]
|
|
9
|
+
# @param server [WEBrick::HTTPServer] the HTTP server instance
|
|
10
|
+
# @param web_auth [WebAuth] the WebAuth instance to record the callback
|
|
11
11
|
def initialize(server, web_auth)
|
|
12
12
|
Log.log.debug('WebAuthServlet initialize')
|
|
13
13
|
super(server)
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'webrick'
|
|
4
|
-
require 'webrick/https'
|
|
5
4
|
require 'aspera/log'
|
|
6
5
|
require 'aspera/assert'
|
|
7
6
|
require 'aspera/hash_ext'
|
|
8
|
-
require 'openssl'
|
|
9
7
|
|
|
10
8
|
module Aspera
|
|
11
9
|
# Simple WEBrick server with HTTPS support
|
|
@@ -42,7 +40,7 @@ module Aspera
|
|
|
42
40
|
cert
|
|
43
41
|
end
|
|
44
42
|
|
|
45
|
-
# @return
|
|
43
|
+
# @return [Array<OpenSSL::X509::Certificate>] list of Certificates from chain file
|
|
46
44
|
def read_chain_file(chain)
|
|
47
45
|
File.read(chain).scan(/-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m).map{ |i| OpenSSL::X509::Certificate.new(i)}
|
|
48
46
|
end
|
|
@@ -66,13 +64,18 @@ module Aspera
|
|
|
66
64
|
when 'http'
|
|
67
65
|
Log.log.debug('HTTP mode')
|
|
68
66
|
when 'https'
|
|
67
|
+
# Required lazily: webrick/ssl.rb reads OpenSSL::OPENSSL_VERSION at load time,
|
|
68
|
+
# a constant CosmoRuby's OpenSSL shim does not define, so requiring it
|
|
69
|
+
# unconditionally at file load would break any command in a Cosmo build
|
|
70
|
+
# even when no HTTPS server is ever started.
|
|
71
|
+
require 'webrick/https'
|
|
69
72
|
webrick_options[:SSLEnable] = true
|
|
70
73
|
if cert.nil? && key.nil?
|
|
71
74
|
webrick_options[:SSLCertName] = [['CN', WEBrick::Utils.getservername]]
|
|
72
75
|
elsif cert && PKCS12_EXT.include?(File.extname(cert).downcase)
|
|
73
76
|
# PKCS12
|
|
74
77
|
Log.log.debug('Using PKCS12 certificate')
|
|
75
|
-
|
|
78
|
+
Aspera.assert(!key.nil?, type: Error){'PKCS12 requires a key (password)'}
|
|
76
79
|
pkcs12 = OpenSSL::PKCS12.new(File.read(cert), key)
|
|
77
80
|
webrick_options[:SSLCertificate] = pkcs12.certificate
|
|
78
81
|
webrick_options[:SSLPrivateKey] = pkcs12.key
|
|
@@ -90,7 +93,7 @@ module Aspera
|
|
|
90
93
|
OpenSSL::X509::Certificate.new(File.read(cert))
|
|
91
94
|
end
|
|
92
95
|
webrick_options[:SSLExtraChainCert] = read_chain_file(chain) unless chain.nil?
|
|
93
|
-
|
|
96
|
+
Aspera.assert(webrick_options[:SSLCertificate].public_key.to_der == webrick_options[:SSLPrivateKey].public_key.to_der, type: Error){'key and cert do not match'}
|
|
94
97
|
end
|
|
95
98
|
end
|
|
96
99
|
# call constructor of parent class, but capture STDERR
|
data/lib/aspera/yaml.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'aspera/assert'
|
|
3
4
|
require 'yaml'
|
|
4
5
|
|
|
5
6
|
module Aspera
|
|
@@ -42,7 +43,7 @@ module Aspera
|
|
|
42
43
|
# @raise [RuntimeError] If duplicate keys are found
|
|
43
44
|
def safe_load(yaml)
|
|
44
45
|
duplicate_keys = find_duplicate_keys(Psych.parse_stream(yaml))
|
|
45
|
-
|
|
46
|
+
Aspera.assert(duplicate_keys.empty?){"Duplicate keys: #{duplicate_keys.join('; ')}"}
|
|
46
47
|
YAML.safe_load(yaml, permitted_classes: [Time, Date, Symbol])
|
|
47
48
|
end
|
|
48
49
|
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: aspera-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.
|
|
4
|
+
version: 4.27.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Laurent Martin
|
|
@@ -319,6 +319,8 @@ files:
|
|
|
319
319
|
- README.md
|
|
320
320
|
- bin/ascli
|
|
321
321
|
- bin/asession
|
|
322
|
+
- docs/README.md
|
|
323
|
+
- docs/test-mcp-with-ai.md
|
|
322
324
|
- lib/aspera/agent/base.rb
|
|
323
325
|
- lib/aspera/agent/connect.rb
|
|
324
326
|
- lib/aspera/agent/desktop.rb
|
|
@@ -334,19 +336,29 @@ files:
|
|
|
334
336
|
- lib/aspera/api/faspex.rb
|
|
335
337
|
- lib/aspera/api/httpgw.rb
|
|
336
338
|
- lib/aspera/api/node.rb
|
|
339
|
+
- lib/aspera/api/queries/bss_subscription_account.graphql
|
|
340
|
+
- lib/aspera/api/queries/bss_subscription_usage.graphql
|
|
337
341
|
- lib/aspera/ascmd.rb
|
|
338
342
|
- lib/aspera/ascp/installation.rb
|
|
339
343
|
- lib/aspera/ascp/management.rb
|
|
340
344
|
- lib/aspera/assert.rb
|
|
345
|
+
- lib/aspera/cli/ascp_actions.rb
|
|
346
|
+
- lib/aspera/cli/async_transfer_store.rb
|
|
347
|
+
- lib/aspera/cli/bootstrapper.rb
|
|
348
|
+
- lib/aspera/cli/command_registry.rb
|
|
349
|
+
- lib/aspera/cli/command_spec.rb
|
|
341
350
|
- lib/aspera/cli/context.rb
|
|
342
351
|
- lib/aspera/cli/error.rb
|
|
343
352
|
- lib/aspera/cli/extended_value.rb
|
|
344
353
|
- lib/aspera/cli/formatter.rb
|
|
354
|
+
- lib/aspera/cli/gem_checker.rb
|
|
345
355
|
- lib/aspera/cli/hints.rb
|
|
346
356
|
- lib/aspera/cli/http.rb
|
|
347
357
|
- lib/aspera/cli/info.rb
|
|
348
|
-
- lib/aspera/cli/
|
|
358
|
+
- lib/aspera/cli/mailer.rb
|
|
359
|
+
- lib/aspera/cli/mcp_tool.rb
|
|
349
360
|
- lib/aspera/cli/options.schema.yaml
|
|
361
|
+
- lib/aspera/cli/parser.rb
|
|
350
362
|
- lib/aspera/cli/plugins/alee.rb
|
|
351
363
|
- lib/aspera/cli/plugins/aoc.rb
|
|
352
364
|
- lib/aspera/cli/plugins/ats.rb
|
|
@@ -360,20 +372,25 @@ files:
|
|
|
360
372
|
- lib/aspera/cli/plugins/faspex5.rb
|
|
361
373
|
- lib/aspera/cli/plugins/faspio.rb
|
|
362
374
|
- lib/aspera/cli/plugins/httpgw.rb
|
|
375
|
+
- lib/aspera/cli/plugins/mcp.rb
|
|
363
376
|
- lib/aspera/cli/plugins/node.rb
|
|
364
377
|
- lib/aspera/cli/plugins/oauth.rb
|
|
365
378
|
- lib/aspera/cli/plugins/orchestrator.rb
|
|
366
379
|
- lib/aspera/cli/plugins/preview.rb
|
|
367
380
|
- lib/aspera/cli/plugins/server.rb
|
|
368
381
|
- lib/aspera/cli/plugins/shares.rb
|
|
382
|
+
- lib/aspera/cli/preset_actions.rb
|
|
369
383
|
- lib/aspera/cli/preset_manager.rb
|
|
370
384
|
- lib/aspera/cli/result.rb
|
|
371
385
|
- lib/aspera/cli/runner.rb
|
|
386
|
+
- lib/aspera/cli/secret_finder.rb
|
|
372
387
|
- lib/aspera/cli/special_values.rb
|
|
373
388
|
- lib/aspera/cli/sync_actions.rb
|
|
374
389
|
- lib/aspera/cli/terminal_formatter.rb
|
|
390
|
+
- lib/aspera/cli/transfer_actions.rb
|
|
375
391
|
- lib/aspera/cli/transfer_agent.rb
|
|
376
392
|
- lib/aspera/cli/transfer_progress.rb
|
|
393
|
+
- lib/aspera/cli/vault_manager.rb
|
|
377
394
|
- lib/aspera/cli/version.rb
|
|
378
395
|
- lib/aspera/cli/wizard.rb
|
|
379
396
|
- lib/aspera/colors.rb
|
|
@@ -389,18 +406,22 @@ files:
|
|
|
389
406
|
- lib/aspera/data_repository.rb
|
|
390
407
|
- lib/aspera/dot_container.rb
|
|
391
408
|
- lib/aspera/environment.rb
|
|
409
|
+
- lib/aspera/exec_spec.rb
|
|
392
410
|
- lib/aspera/faspex_gw.rb
|
|
393
411
|
- lib/aspera/faspex_postproc.rb
|
|
394
412
|
- lib/aspera/formatter_interface.rb
|
|
413
|
+
- lib/aspera/graphql.rb
|
|
395
414
|
- lib/aspera/hash_ext.rb
|
|
396
415
|
- lib/aspera/id_generator.rb
|
|
397
|
-
- lib/aspera/json_rpc.rb
|
|
416
|
+
- lib/aspera/json_rpc/client.rb
|
|
417
|
+
- lib/aspera/json_rpc/version.rb
|
|
398
418
|
- lib/aspera/keychain/base.rb
|
|
399
419
|
- lib/aspera/keychain/encrypted_hash.rb
|
|
400
420
|
- lib/aspera/keychain/factory.rb
|
|
401
421
|
- lib/aspera/keychain/hashicorp_vault.rb
|
|
402
422
|
- lib/aspera/keychain/macos_security.rb
|
|
403
423
|
- lib/aspera/line_logger.rb
|
|
424
|
+
- lib/aspera/link_header.rb
|
|
404
425
|
- lib/aspera/log.rb
|
|
405
426
|
- lib/aspera/markdown.rb
|
|
406
427
|
- lib/aspera/nagios.rb
|
|
@@ -451,6 +472,7 @@ files:
|
|
|
451
472
|
- lib/aspera/transfer/error.rb
|
|
452
473
|
- lib/aspera/transfer/faux_file.rb
|
|
453
474
|
- lib/aspera/transfer/parameters.rb
|
|
475
|
+
- lib/aspera/transfer/result.rb
|
|
454
476
|
- lib/aspera/transfer/resumer.rb
|
|
455
477
|
- lib/aspera/transfer/spec.rb
|
|
456
478
|
- lib/aspera/transfer/spec.schema.yaml
|
metadata.gz.sig
CHANGED
|
Binary file
|
data/lib/aspera/json_rpc.rb
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# cspell:ignore blankslate
|
|
4
|
-
|
|
5
|
-
require 'aspera/rest_error_analyzer'
|
|
6
|
-
require 'aspera/assert'
|
|
7
|
-
require 'blankslate'
|
|
8
|
-
|
|
9
|
-
Aspera::RestErrorAnalyzer.instance.add_simple_handler(name: 'JSON RPC', path: %w[error message], always: true)
|
|
10
|
-
|
|
11
|
-
module Aspera
|
|
12
|
-
# a very simple JSON RPC client
|
|
13
|
-
class JsonRpcClient < BlankSlate
|
|
14
|
-
JSON_RPC_VERSION = '2.0'
|
|
15
|
-
reveal :instance_variable_get
|
|
16
|
-
reveal :inspect
|
|
17
|
-
reveal :to_s
|
|
18
|
-
|
|
19
|
-
def initialize(api, namespace = nil)
|
|
20
|
-
super()
|
|
21
|
-
@api = api
|
|
22
|
-
@namespace = namespace
|
|
23
|
-
@request_id = 0
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def respond_to_missing?(_sym, _include_private = false)
|
|
27
|
-
true
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def method_missing(method, *args, &block)
|
|
31
|
-
args = args.first if args.size == 1 && args.first.is_a?(Hash)
|
|
32
|
-
data = @api.create('', {
|
|
33
|
-
jsonrpc: JSON_RPC_VERSION,
|
|
34
|
-
method: "#{@namespace}#{method}",
|
|
35
|
-
params: args,
|
|
36
|
-
id: @request_id += 1
|
|
37
|
-
})
|
|
38
|
-
Aspera.assert_type(data, Hash){'response'}
|
|
39
|
-
Aspera.assert(data['jsonrpc'] == JSON_RPC_VERSION, 'bad version in response')
|
|
40
|
-
Aspera.assert(data.key?('id'), 'missing id in response')
|
|
41
|
-
Aspera.assert(!(data.key?('error') && data.key?('result')), 'both error and response')
|
|
42
|
-
Aspera.assert(
|
|
43
|
-
!data.key?('error') ||
|
|
44
|
-
data['error'].is_a?(Hash) &&
|
|
45
|
-
data['error']['code'].is_a?(Integer) &&
|
|
46
|
-
data['error']['message'].is_a?(String),
|
|
47
|
-
'bad error response'
|
|
48
|
-
)
|
|
49
|
-
return data['result']
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|