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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +29 -0
- data/CONTRIBUTING.md +1 -7
- data/TODO.md +50 -0
- data/docs/README.md +708 -488
- data/lib/aspera/agent/base.rb +10 -2
- data/lib/aspera/agent/connect.rb +7 -7
- data/lib/aspera/agent/desktop.rb +3 -3
- data/lib/aspera/agent/direct.rb +48 -19
- data/lib/aspera/agent/factory.rb +3 -3
- data/lib/aspera/agent/httpgw.rb +55 -14
- data/lib/aspera/agent/node.rb +2 -2
- data/lib/aspera/agent/transferd.rb +12 -12
- data/lib/aspera/api/aoc.rb +28 -28
- data/lib/aspera/api/cos_node.rb +10 -9
- data/lib/aspera/api/faspex.rb +2 -2
- data/lib/aspera/api/httpgw.rb +20 -20
- data/lib/aspera/api/node.rb +31 -53
- data/lib/aspera/ascmd.rb +13 -13
- data/lib/aspera/ascp/installation.rb +43 -36
- data/lib/aspera/ascp/management.rb +6 -6
- data/lib/aspera/assert.rb +12 -13
- data/lib/aspera/cli/ascp_actions.rb +7 -7
- data/lib/aspera/cli/async_transfer_store.rb +49 -5
- data/lib/aspera/cli/bootstrapper.rb +9 -9
- data/lib/aspera/cli/command_registry.rb +1 -1
- data/lib/aspera/cli/command_spec.rb +6 -3
- data/lib/aspera/cli/context.rb +3 -3
- data/lib/aspera/cli/extended_value.rb +26 -26
- data/lib/aspera/cli/formatter.rb +76 -54
- data/lib/aspera/cli/gem_checker.rb +1 -1
- data/lib/aspera/cli/hints.rb +2 -2
- data/lib/aspera/cli/http.rb +22 -29
- data/lib/aspera/cli/mailer.rb +7 -7
- data/lib/aspera/cli/mcp_tool.rb +31 -4
- data/lib/aspera/cli/option_declarator.rb +77 -0
- data/lib/aspera/cli/options.schema.yaml +273 -3
- data/lib/aspera/cli/parser.rb +539 -280
- data/lib/aspera/cli/plugins/alee.rb +1 -1
- data/lib/aspera/cli/plugins/aoc.rb +297 -313
- data/lib/aspera/cli/plugins/ats.rb +25 -21
- data/lib/aspera/cli/plugins/base.rb +357 -186
- data/lib/aspera/cli/plugins/basic_auth.rb +0 -12
- data/lib/aspera/cli/plugins/config.rb +76 -73
- data/lib/aspera/cli/plugins/console.rb +8 -8
- data/lib/aspera/cli/plugins/cos.rb +4 -3
- data/lib/aspera/cli/plugins/factory.rb +2 -2
- data/lib/aspera/cli/plugins/faspex5.rb +259 -248
- data/lib/aspera/cli/plugins/faspio.rb +7 -2
- data/lib/aspera/cli/plugins/httpgw.rb +1 -1
- data/lib/aspera/cli/plugins/mcp.rb +11 -11
- data/lib/aspera/cli/plugins/node.rb +227 -283
- data/lib/aspera/cli/plugins/orchestrator.rb +23 -23
- data/lib/aspera/cli/plugins/preview.rb +61 -64
- data/lib/aspera/cli/plugins/server.rb +36 -31
- data/lib/aspera/cli/plugins/shares.rb +174 -135
- data/lib/aspera/cli/preset_actions.rb +39 -19
- data/lib/aspera/cli/preset_manager.rb +74 -32
- data/lib/aspera/cli/result.rb +18 -16
- data/lib/aspera/cli/runner.rb +75 -39
- data/lib/aspera/cli/secret_finder.rb +1 -1
- data/lib/aspera/cli/sync_actions.rb +36 -35
- data/lib/aspera/cli/terminal_formatter.rb +2 -2
- data/lib/aspera/cli/transfer_actions.rb +17 -10
- data/lib/aspera/cli/transfer_agent.rb +44 -44
- data/lib/aspera/cli/transfer_progress.rb +7 -7
- data/lib/aspera/cli/vault_manager.rb +34 -12
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +17 -20
- data/lib/aspera/colors.rb +3 -3
- data/lib/aspera/command_line_builder.rb +16 -16
- data/lib/aspera/command_line_converter.rb +1 -1
- data/lib/aspera/coverage.rb +1 -2
- data/lib/aspera/data_repository.rb +1 -1
- data/lib/aspera/dot_container.rb +8 -8
- data/lib/aspera/environment.rb +12 -12
- data/lib/aspera/faspex_gw.rb +4 -4
- data/lib/aspera/faspex_postproc.rb +14 -9
- data/lib/aspera/graphql.rb +4 -2
- data/lib/aspera/hash_ext.rb +2 -2
- data/lib/aspera/json_rpc/client.rb +1 -1
- data/lib/aspera/keychain/base.rb +10 -3
- data/lib/aspera/keychain/encrypted_hash.rb +92 -17
- data/lib/aspera/keychain/factory.rb +17 -5
- data/lib/aspera/keychain/hashicorp_vault.rb +1 -1
- data/lib/aspera/keychain/macos_security.rb +23 -25
- data/lib/aspera/keychain/one_password_api.rb +86 -0
- data/lib/aspera/keychain/one_password_base.rb +34 -0
- data/lib/aspera/keychain/one_password_cli.rb +98 -0
- data/lib/aspera/link_header.rb +2 -2
- data/lib/aspera/log.rb +13 -13
- data/lib/aspera/markdown.rb +5 -5
- data/lib/aspera/nagios.rb +8 -8
- data/lib/aspera/node_simulator.rb +33 -27
- data/lib/aspera/oauth/base.rb +4 -5
- data/lib/aspera/oauth/boot.rb +3 -3
- data/lib/aspera/oauth/factory.rb +5 -5
- data/lib/aspera/oauth/jwt.rb +5 -7
- data/lib/aspera/oauth/web.rb +4 -4
- data/lib/aspera/persistency_action_once.rb +4 -4
- data/lib/aspera/persistency_folder.rb +8 -8
- data/lib/aspera/preview/file_types.rb +4 -4
- data/lib/aspera/preview/generator.rb +49 -46
- data/lib/aspera/preview/options.rb +3 -2
- data/lib/aspera/preview/terminal.rb +5 -5
- data/lib/aspera/preview/utils.rb +65 -18
- data/lib/aspera/products/connect.rb +2 -2
- data/lib/aspera/products/desktop.rb +1 -1
- data/lib/aspera/products/other.rb +2 -2
- data/lib/aspera/products/transferd.rb +3 -3
- data/lib/aspera/proxy_auto_config.rb +10 -10
- data/lib/aspera/rest.rb +149 -115
- data/lib/aspera/rest_error_analyzer.rb +3 -3
- data/lib/aspera/rest_list.rb +10 -9
- data/lib/aspera/schema/IBM Aspera Node API-4.4.6.yaml +6232 -0
- data/lib/aspera/schema/IBM Aspera faspio Gateway API-1.0.0.yaml +249 -0
- data/lib/aspera/schema/IBM_Aspera_Shares.yaml +4653 -0
- data/lib/aspera/schema/documentation.rb +17 -11
- data/lib/aspera/schema/reader.rb +78 -4
- data/lib/aspera/schema/registry.rb +26 -7
- data/lib/aspera/secret_hider.rb +5 -5
- data/lib/aspera/ssh.rb +64 -31
- data/lib/aspera/ssl.rb +3 -3
- data/lib/aspera/sync/database.rb +2 -2
- data/lib/aspera/sync/operations.rb +13 -13
- data/lib/aspera/temp_file_manager.rb +24 -4
- data/lib/aspera/transfer/faux_file.rb +2 -2
- data/lib/aspera/transfer/parameters.rb +15 -15
- data/lib/aspera/transfer/resumer.rb +9 -9
- data/lib/aspera/transfer/spec.rb +1 -1
- data/lib/aspera/uri_reader.rb +52 -15
- data/lib/aspera/web_auth.rb +6 -5
- data/lib/aspera/web_server_simple.rb +9 -9
- data/lib/aspera/yaml.rb +4 -4
- data.tar.gz.sig +0 -0
- metadata +10 -4
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/plugins/faspex.rb +0 -576
- data/lib/aspera/transfer/uri.rb +0 -56
|
@@ -21,9 +21,9 @@ module Aspera
|
|
|
21
21
|
def create(name)
|
|
22
22
|
return unless name.start_with?(PREFIX)
|
|
23
23
|
name_params = name.delete_prefix(PREFIX).split('?', 2)
|
|
24
|
-
Aspera.assert(name_params.length.eql?(2), type: Error){"Format: #{PREFIX}<file path>?<size>"}
|
|
24
|
+
Aspera.assert(name_params.length.eql?(2), type: Error) { "Format: #{PREFIX}<file path>?<size>" }
|
|
25
25
|
m = name_params[1].downcase.match(/^(\d+)([#{SIZE_UNITS.join('')}]?)$/)
|
|
26
|
-
Aspera.assert(m, type: Error){"Format: <integer>[#{SIZE_UNITS.join(',')}]"}
|
|
26
|
+
Aspera.assert(m, type: Error) { "Format: <integer>[#{SIZE_UNITS.join(',')}]" }
|
|
27
27
|
size = m[2].empty? ? m[1].to_i : m[1].to_i * (1024**(SIZE_UNITS.index(m[2]) + 1))
|
|
28
28
|
return FauxFile.new(name_params[0], size)
|
|
29
29
|
end
|
|
@@ -36,14 +36,14 @@ module Aspera
|
|
|
36
36
|
# because of garbage collection takes any file there
|
|
37
37
|
# this could be refined, as, for example, on macos, temp folder is already user specific
|
|
38
38
|
def file_list_folder
|
|
39
|
-
@file_list_folder ||= TempFileManager.instance.
|
|
39
|
+
@file_list_folder ||= TempFileManager.instance.new_dir_path_global('asession_filelists')
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
# Check whether a file list option is already present in the `ascp` argument list
|
|
43
43
|
# @param ascp_args [Array, nil] `ascp` arguments
|
|
44
44
|
# @return [Boolean] true if a file list option is present
|
|
45
45
|
def ascp_args_file_list?(ascp_args)
|
|
46
|
-
ascp_args&.any?{ |i| FILE_LIST_OPTIONS.include?(i)}
|
|
46
|
+
ascp_args&.any? { |i| FILE_LIST_OPTIONS.include?(i) }
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
@@ -68,12 +68,12 @@ module Aspera
|
|
|
68
68
|
@job_spec = job_spec
|
|
69
69
|
Aspera.assert_type(@job_spec, Hash)
|
|
70
70
|
@ascp_args = ascp_args.nil? ? [] : ascp_args
|
|
71
|
-
Aspera.assert_array_all(@ascp_args, String){'ascp_args'}
|
|
71
|
+
Aspera.assert_array_all(@ascp_args, String) { 'ascp_args' }
|
|
72
72
|
@wss = wss
|
|
73
73
|
@quiet = quiet
|
|
74
74
|
@file_list = file_list
|
|
75
75
|
@trusted_certs = trusted_certs.nil? ? [] : trusted_certs
|
|
76
|
-
Aspera.assert_type(@trusted_certs, Array){'trusted_certs'}
|
|
76
|
+
Aspera.assert_type(@trusted_certs, Array) { 'trusted_certs' }
|
|
77
77
|
@client_ssh_key = client_ssh_key.nil? ? :rsa : client_ssh_key.to_sym
|
|
78
78
|
Aspera.assert_values(@client_ssh_key, Ascp::Installation::CLIENT_SSH_KEY_OPTIONS)
|
|
79
79
|
@check_ignore_cb = check_ignore_cb
|
|
@@ -92,27 +92,27 @@ module Aspera
|
|
|
92
92
|
# transfer spec contains paths ?
|
|
93
93
|
if !ts_paths_array.nil?
|
|
94
94
|
Aspera.assert(!ascp_file_list_provided, 'file list provided both in transfer spec and ascp file list. Remove one of them.')
|
|
95
|
-
Aspera.assert(ts_paths_array.all?{ |i| i.key?('source')}, "All elements of paths must have a 'source' key")
|
|
96
|
-
is_pair_list = ts_paths_array.any?{ |i| i.key?('destination')}
|
|
97
|
-
Aspera.assert(!(is_pair_list && !ts_paths_array.all?{ |i| i.key?('destination')})){"All elements of paths must be consistent with 'destination' key"}
|
|
95
|
+
Aspera.assert(ts_paths_array.all? { |i| i.key?('source') }, "All elements of paths must have a 'source' key")
|
|
96
|
+
is_pair_list = ts_paths_array.any? { |i| i.key?('destination') }
|
|
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
98
|
if !@file_list || self.class.file_list_folder.nil?
|
|
99
99
|
Aspera.assert(!is_pair_list, 'file pair list is not supported when file list folder is not set')
|
|
100
100
|
# not safe for special characters ? (maybe not, depends on OS)
|
|
101
101
|
Log.log.debug('placing source file list on command line (no file list file)')
|
|
102
|
-
@builder.add_command_line_options(ts_paths_array.map{ |i| i['source']})
|
|
102
|
+
@builder.add_command_line_options(ts_paths_array.map { |i| i['source'] })
|
|
103
103
|
else
|
|
104
104
|
# safer option: generate a file list file if there is storage defined for it
|
|
105
105
|
if is_pair_list
|
|
106
106
|
file_list_option = '--file-pair-list'
|
|
107
|
-
lines = ts_paths_array.each_with_object([]){ |e, m| m.push(e['source'], e['destination'])}
|
|
107
|
+
lines = ts_paths_array.each_with_object([]) { |e, m| m.push(e['source'], e['destination']) }
|
|
108
108
|
else
|
|
109
109
|
file_list_option = '--file-list'
|
|
110
|
-
lines = ts_paths_array.map{ |i| i['source']}
|
|
110
|
+
lines = ts_paths_array.map { |i| i['source'] }
|
|
111
111
|
end
|
|
112
112
|
file_list_file = TempFileManager.instance.new_file_path_in_folder(self.class.file_list_folder)
|
|
113
113
|
Log.dump(:file_list, lines)
|
|
114
114
|
File.write(file_list_file, lines.join("\n"), encoding: 'UTF-8')
|
|
115
|
-
Log.log.debug{"#{file_list_option}=\n#{File.read(file_list_file)}".red}
|
|
115
|
+
Log.log.debug { "#{file_list_option}=\n#{File.read(file_list_file)}".red }
|
|
116
116
|
end
|
|
117
117
|
end
|
|
118
118
|
@builder.add_command_line_options("#{file_list_option}=#{file_list_file}") unless file_list_option.nil?
|
|
@@ -172,11 +172,11 @@ module Aspera
|
|
|
172
172
|
|
|
173
173
|
case (delete_source = @builder.read_param('delete_source'))
|
|
174
174
|
when true
|
|
175
|
-
DELETE_EQUIV.each{ |i| @job_spec[i] = true}
|
|
175
|
+
DELETE_EQUIV.each { |i| @job_spec[i] = true }
|
|
176
176
|
when false
|
|
177
|
-
DELETE_EQUIV.each{ |i| @job_spec.delete(i)}
|
|
177
|
+
DELETE_EQUIV.each { |i| @job_spec.delete(i) }
|
|
178
178
|
when nil
|
|
179
|
-
else Aspera.error_unexpected_value(delete_source){'delete_source'}
|
|
179
|
+
else Aspera.error_unexpected_value(delete_source) { 'delete_source' }
|
|
180
180
|
end
|
|
181
181
|
|
|
182
182
|
# process parameters as specified in table
|
|
@@ -211,7 +211,7 @@ module Aspera
|
|
|
211
211
|
end
|
|
212
212
|
# disable redis in client, only for ascp, this makes ascp4 fail
|
|
213
213
|
exec_spec.env['ASPERA_TEST_REDIS_DISABLE'] = 'true' if exec_spec.exec.eql?(:ascp)
|
|
214
|
-
Log.log.debug{"ascp args: #{exec_spec}"}
|
|
214
|
+
Log.log.debug { "ascp args: #{exec_spec}" }
|
|
215
215
|
return exec_spec
|
|
216
216
|
end
|
|
217
217
|
DELETE_EQUIV = %w[remove_after_transfer remove_empty_directories remove_empty_source_directory]
|
|
@@ -19,13 +19,13 @@ module Aspera
|
|
|
19
19
|
sleep_factor: 2,
|
|
20
20
|
sleep_max: 60
|
|
21
21
|
)
|
|
22
|
-
Aspera.assert_type(iter_max, Integer){'iter_max'}
|
|
22
|
+
Aspera.assert_type(iter_max, Integer) { 'iter_max' }
|
|
23
23
|
@iter_max = iter_max
|
|
24
|
-
Aspera.assert_type(sleep_initial, Integer){'sleep_initial'}
|
|
24
|
+
Aspera.assert_type(sleep_initial, Integer) { 'sleep_initial' }
|
|
25
25
|
@sleep_initial = sleep_initial
|
|
26
|
-
Aspera.assert_type(sleep_factor, Integer){'sleep_factor'}
|
|
26
|
+
Aspera.assert_type(sleep_factor, Integer) { 'sleep_factor' }
|
|
27
27
|
@sleep_factor = sleep_factor
|
|
28
|
-
Aspera.assert_type(sleep_max, Integer){'sleep_max'}
|
|
28
|
+
Aspera.assert_type(sleep_max, Integer) { 'sleep_max' }
|
|
29
29
|
@sleep_max = sleep_max
|
|
30
30
|
end
|
|
31
31
|
|
|
@@ -38,7 +38,7 @@ module Aspera
|
|
|
38
38
|
# maximum of retry
|
|
39
39
|
remaining_resumes = @iter_max
|
|
40
40
|
sleep_seconds = @sleep_initial
|
|
41
|
-
Log.log.debug{"retries=#{remaining_resumes}"}
|
|
41
|
+
Log.log.debug { "retries=#{remaining_resumes}" }
|
|
42
42
|
# try to send the file until ascp is successful
|
|
43
43
|
loop do
|
|
44
44
|
Log.log.debug('Starting task execution')
|
|
@@ -48,17 +48,17 @@ module Aspera
|
|
|
48
48
|
# Exit retry loop if success
|
|
49
49
|
break
|
|
50
50
|
rescue Error => e
|
|
51
|
-
Log.log.warn{"An error occurred during task: #{e.message}"}
|
|
52
|
-
Log.log.debug{"Retryable ? #{e.retryable?}"}
|
|
51
|
+
Log.log.warn { "An error occurred during task: #{e.message}" }
|
|
52
|
+
Log.log.debug { "Retryable ? #{e.retryable?}" }
|
|
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
|
-
Aspera.assert(remaining_resumes > 0, type: Error){"Maximum number of retry reached: #{@iter_max}"}
|
|
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
|
|
60
60
|
remaining_resumes -= 1
|
|
61
|
-
Log.log.warn{"Resuming in #{sleep_seconds} seconds (retry left:#{remaining_resumes})"}
|
|
61
|
+
Log.log.warn { "Resuming in #{sleep_seconds} seconds (retry left:#{remaining_resumes})" }
|
|
62
62
|
|
|
63
63
|
# wait a bit before retrying, maybe network condition will be better
|
|
64
64
|
sleep(sleep_seconds)
|
data/lib/aspera/transfer/spec.rb
CHANGED
|
@@ -57,7 +57,7 @@ module Aspera
|
|
|
57
57
|
# @return [Integer] value in kbps
|
|
58
58
|
def rate_string_to_kbps(value)
|
|
59
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."}
|
|
60
|
+
Aspera.assert(m) { "Invalid rate value: #{value.inspect}. Expected integer with optional suffix k/K, m/M or g/G." }
|
|
61
61
|
multiplier = m[2] ? RATE_SUFFIX_KBPS.fetch(m[2].downcase) : 1
|
|
62
62
|
return m[1].to_i * multiplier
|
|
63
63
|
end
|
data/lib/aspera/uri_reader.rb
CHANGED
|
@@ -7,31 +7,66 @@ require 'aspera/rest'
|
|
|
7
7
|
require 'aspera/temp_file_manager'
|
|
8
8
|
|
|
9
9
|
module Aspera
|
|
10
|
-
# Read
|
|
10
|
+
# Read content from a URI; supported schemes: file:, http:, https:, data:
|
|
11
|
+
#
|
|
12
|
+
# == file: URL convention
|
|
13
|
+
# Two equivalent forms are accepted:
|
|
14
|
+
#
|
|
15
|
+
# file:///relative/path -> relative path "relative/path"
|
|
16
|
+
# file:////absolute/path -> absolute path "/absolute/path"
|
|
17
|
+
#
|
|
18
|
+
# A shorter form is also accepted (no authority component):
|
|
19
|
+
#
|
|
20
|
+
# file:relative/path -> relative path "relative/path"
|
|
21
|
+
# file:/absolute/path -> absolute path "/absolute/path"
|
|
22
|
+
#
|
|
23
|
+
# The short form is consistent with RFC 8089 (file:///<path> = absolute,
|
|
24
|
+
# file:<path> = relative). Both forms are handled identically by this module.
|
|
25
|
+
# The canonical form built by {file_url} uses the +file:///+ prefix.
|
|
11
26
|
module UriReader
|
|
12
27
|
SCHEME_FILE = 'file'
|
|
13
28
|
SCHEME_FILE_PFX1 = "#{SCHEME_FILE}:"
|
|
29
|
+
# Canonical prefix for file: URLs (no host, three slashes).
|
|
30
|
+
# What follows is the literal path: relative or absolute (starting with a second slash).
|
|
14
31
|
SCHEME_FILE_PFX2 = "#{SCHEME_FILE_PFX1}///"
|
|
15
32
|
private_constant :SCHEME_FILE, :SCHEME_FILE_PFX1, :SCHEME_FILE_PFX2
|
|
16
33
|
class << self
|
|
17
|
-
# @return [Boolean] true if the
|
|
34
|
+
# @return [Boolean] true if +url+ uses the file: scheme recognised by this module
|
|
18
35
|
def file?(url)
|
|
19
|
-
url.start_with?(
|
|
36
|
+
url.start_with?(SCHEME_FILE_PFX1)
|
|
20
37
|
end
|
|
21
38
|
|
|
22
|
-
#
|
|
39
|
+
# Build a file: URL from +path+.
|
|
40
|
+
# A relative path yields +file:///path+; an absolute path yields +file:////path+.
|
|
41
|
+
# @param path [String] relative or absolute file-system path
|
|
42
|
+
# @return [String] corresponding file: URL
|
|
23
43
|
def file_url(path)
|
|
24
44
|
return "#{SCHEME_FILE_PFX2}#{path}"
|
|
25
45
|
end
|
|
26
46
|
|
|
27
|
-
#
|
|
47
|
+
# Extract the file-system path from a file: URL.
|
|
48
|
+
# Accepts both the canonical +file:///+ form and the short +file:+ form.
|
|
49
|
+
# Returns the literal path (relative or absolute) without working-directory expansion.
|
|
50
|
+
# @param url [String] a file: URL (canonical or short form)
|
|
51
|
+
# @return [String] the literal path encoded in the URL
|
|
28
52
|
def file_path(url)
|
|
29
|
-
Aspera.assert(file?(url)){"use format: #{file_url('<path>')}"}
|
|
30
|
-
|
|
53
|
+
Aspera.assert(file?(url)) { "use format: #{file_url('<path>')}" }
|
|
54
|
+
# Strip canonical prefix "file:///" first (covers relative and absolute canonical forms).
|
|
55
|
+
# If absent, strip only the short "file:" prefix.
|
|
56
|
+
return url.start_with?(SCHEME_FILE_PFX2) ? url.delete_prefix(SCHEME_FILE_PFX2) : url.delete_prefix(SCHEME_FILE_PFX1)
|
|
31
57
|
end
|
|
32
58
|
|
|
33
|
-
# Read
|
|
59
|
+
# Read content from a URI and return it as a String.
|
|
60
|
+
# Supported schemes: +http+, +https+, +data+, +file+, and bare paths (no scheme).
|
|
61
|
+
# For file: URLs the path is extracted via {file_path} to respect the module convention
|
|
62
|
+
# (see module-level documentation). Ruby's URI parser is not used for file: URLs because
|
|
63
|
+
# it interprets the three-slash prefix differently (it always produces an absolute path).
|
|
64
|
+
# Bare paths (no scheme) are passed to File.read directly; leading +/~/+, +/./+, +/../+
|
|
65
|
+
# are expanded via +File.expand_path+ after stripping the synthetic leading slash added by
|
|
66
|
+
# URI.
|
|
34
67
|
def read(uri_to_read)
|
|
68
|
+
# Handle file: URLs directly to honour the file:///relative vs file:////absolute convention.
|
|
69
|
+
return File.read(file_path(uri_to_read)) if file?(uri_to_read)
|
|
35
70
|
uri = URI.parse(uri_to_read)
|
|
36
71
|
case uri.scheme
|
|
37
72
|
when 'http', 'https'
|
|
@@ -43,20 +78,22 @@ module Aspera
|
|
|
43
78
|
else
|
|
44
79
|
URI.decode_www_form_component(encoded_data)
|
|
45
80
|
end
|
|
46
|
-
when
|
|
81
|
+
when NilClass
|
|
47
82
|
local_file_path = uri.path
|
|
48
|
-
Aspera.assert(!local_file_path.nil?, type: Error){'URL shall have a path, check syntax'}
|
|
83
|
+
Aspera.assert(!local_file_path.nil?, type: Error) { 'URL shall have a path, check syntax' }
|
|
49
84
|
local_file_path = File.expand_path(local_file_path.gsub(%r{^/}, '')) if %r{^/(~|.|..)/}.match?(local_file_path)
|
|
50
85
|
return File.read(local_file_path)
|
|
51
|
-
else Aspera.error_unexpected_value(uri.scheme){"scheme for [#{uri_to_read}]"}
|
|
86
|
+
else Aspera.error_unexpected_value(uri.scheme) { "scheme for [#{uri_to_read}]" }
|
|
52
87
|
end
|
|
53
88
|
end
|
|
54
89
|
|
|
55
|
-
#
|
|
90
|
+
# Return the local file-system path for the content at +url+, downloading to a temp file if needed.
|
|
91
|
+
# For file: URLs the path is extracted directly (no download).
|
|
92
|
+
# For data: and http(s): URLs the content is written to a temporary file and its path is returned.
|
|
93
|
+
# @return [String] local path to a file containing the URL content
|
|
56
94
|
def read_as_file(url)
|
|
57
95
|
if url.start_with?(SCHEME_FILE_PFX1)
|
|
58
|
-
#
|
|
59
|
-
# require specific file scheme: the path part is "relative", or absolute if there are 4 slash
|
|
96
|
+
# file: scheme: extract the literal path encoded in the URL (relative or absolute).
|
|
60
97
|
return file_path(url)
|
|
61
98
|
elsif url.start_with?('data:')
|
|
62
99
|
# download to temp file
|
|
@@ -68,7 +105,7 @@ module Aspera
|
|
|
68
105
|
# download to temp file
|
|
69
106
|
# auto-delete on exit
|
|
70
107
|
temp_file = TempFileManager.instance.new_file_path_global(suffix: File.basename(url))
|
|
71
|
-
Aspera::Rest.new(base_url: url, redirect_max: 3).call(operation: 'GET',
|
|
108
|
+
Aspera::Rest.new(base_url: url, redirect_max: 3).call(operation: 'GET', save_to: temp_file)
|
|
72
109
|
return temp_file
|
|
73
110
|
end
|
|
74
111
|
end
|
data/lib/aspera/web_auth.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'aspera/web_server_simple'
|
|
4
4
|
require 'aspera/assert'
|
|
5
|
+
require 'erb'
|
|
5
6
|
|
|
6
7
|
module Aspera
|
|
7
8
|
# servlet called on callback: it records the callback request
|
|
@@ -15,8 +16,8 @@ module Aspera
|
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def service(request, response)
|
|
18
|
-
Log.log.debug{"received request from browser #{request.request_method} #{request.path}"}
|
|
19
|
-
Aspera.assert_values(request.request_method, ['GET'], type: WEBrick::HTTPStatus::MethodNotAllowed){'HTTP verb'}
|
|
19
|
+
Log.log.debug { "received request from browser #{request.request_method} #{request.path}" }
|
|
20
|
+
Aspera.assert_values(request.request_method, ['GET'], type: WEBrick::HTTPStatus::MethodNotAllowed) { 'HTTP verb' }
|
|
20
21
|
additional_info = @web_auth.signal_request(request)
|
|
21
22
|
response.status = 200
|
|
22
23
|
response.content_type = 'text/html'
|
|
@@ -91,7 +92,7 @@ module Aspera
|
|
|
91
92
|
<body>
|
|
92
93
|
<h1>Thank You!</h1>
|
|
93
94
|
<p>You can close this window.</p>
|
|
94
|
-
<p>#{additional_info}</p>
|
|
95
|
+
<p>#{ERB::Util.html_escape(additional_info) unless additional_info.nil?}</p>
|
|
95
96
|
|
|
96
97
|
<!-- JavaScript to generate IBM logos -->
|
|
97
98
|
<script>
|
|
@@ -182,7 +183,7 @@ module Aspera
|
|
|
182
183
|
# last argument (self) is provided to constructor of servlet
|
|
183
184
|
mount(@expected_path, WebAuthServlet, self)
|
|
184
185
|
# server runs in thread
|
|
185
|
-
Thread.new{start}
|
|
186
|
+
Thread.new { start }
|
|
186
187
|
end
|
|
187
188
|
|
|
188
189
|
# Called by web server thread on received request
|
|
@@ -201,7 +202,7 @@ module Aspera
|
|
|
201
202
|
# @return [Hash] the query
|
|
202
203
|
def received_request
|
|
203
204
|
# wait for signal from thread
|
|
204
|
-
@mutex.synchronize{@cond.wait(@mutex)}
|
|
205
|
+
@mutex.synchronize { @cond.wait(@mutex) }
|
|
205
206
|
# tell server thread to stop
|
|
206
207
|
shutdown
|
|
207
208
|
return @query
|
|
@@ -12,7 +12,7 @@ module Aspera
|
|
|
12
12
|
DEFAULT_URL = 'http://localhost:8080'
|
|
13
13
|
GENERIC_ISSUER = '/C=FR/O=Test/OU=Test/CN=Test'
|
|
14
14
|
ONE_YEAR_SECONDS = 365 * 24 * 60 * 60
|
|
15
|
-
PKCS12_EXT = %w[p12 pfx].map{ |i| ".#{i}"}.freeze
|
|
15
|
+
PKCS12_EXT = %w[p12 pfx].map { |i| ".#{i}" }.freeze
|
|
16
16
|
CLOCK_SKEW_OFFSET_SEC = 5
|
|
17
17
|
|
|
18
18
|
private_constant :GENERIC_ISSUER, :ONE_YEAR_SECONDS, :PKCS12_EXT, :CLOCK_SKEW_OFFSET_SEC
|
|
@@ -42,7 +42,7 @@ module Aspera
|
|
|
42
42
|
|
|
43
43
|
# @return [Array<OpenSSL::X509::Certificate>] list of Certificates from chain file
|
|
44
44
|
def read_chain_file(chain)
|
|
45
|
-
File.read(chain).scan(/-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m).map{ |i| OpenSSL::X509::Certificate.new(i)}
|
|
45
|
+
File.read(chain).scan(/-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m).map { |i| OpenSSL::X509::Certificate.new(i) }
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
@@ -75,7 +75,7 @@ module Aspera
|
|
|
75
75
|
elsif cert && PKCS12_EXT.include?(File.extname(cert).downcase)
|
|
76
76
|
# PKCS12
|
|
77
77
|
Log.log.debug('Using PKCS12 certificate')
|
|
78
|
-
Aspera.assert(!key.nil?, type: Error){'PKCS12 requires a key (password)'}
|
|
78
|
+
Aspera.assert(!key.nil?, type: Error) { 'PKCS12 requires a key (password)' }
|
|
79
79
|
pkcs12 = OpenSSL::PKCS12.new(File.read(cert), key)
|
|
80
80
|
webrick_options[:SSLCertificate] = pkcs12.certificate
|
|
81
81
|
webrick_options[:SSLPrivateKey] = pkcs12.key
|
|
@@ -93,27 +93,27 @@ module Aspera
|
|
|
93
93
|
OpenSSL::X509::Certificate.new(File.read(cert))
|
|
94
94
|
end
|
|
95
95
|
webrick_options[:SSLExtraChainCert] = read_chain_file(chain) unless chain.nil?
|
|
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'}
|
|
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' }
|
|
97
97
|
end
|
|
98
98
|
end
|
|
99
99
|
# call constructor of parent class, but capture STDERR
|
|
100
100
|
# self signed certificate generates characters on STDERR
|
|
101
101
|
# see create_self_signed_cert in webrick/ssl.rb
|
|
102
|
-
Log.capture_stderr{super(webrick_options)}
|
|
102
|
+
Log.capture_stderr { super(webrick_options) }
|
|
103
103
|
end
|
|
104
104
|
|
|
105
105
|
# blocking
|
|
106
106
|
def start
|
|
107
|
-
Log.log.info{"Listening on #{@uri}"}
|
|
107
|
+
Log.log.info { "Listening on #{@uri}" }
|
|
108
108
|
# kill (-TERM) for graceful shutdown
|
|
109
|
-
handler = proc{shutdown}
|
|
110
|
-
%i{INT TERM}.each{ |sig| trap(sig, &handler)}
|
|
109
|
+
handler = proc { shutdown }
|
|
110
|
+
%i{INT TERM}.each { |sig| trap(sig, &handler) }
|
|
111
111
|
super
|
|
112
112
|
end
|
|
113
113
|
|
|
114
114
|
# log web server access ( option AccessLog )
|
|
115
115
|
def <<(access_log)
|
|
116
|
-
Log.log.debug{"webrick log #{access_log.chomp}"}
|
|
116
|
+
Log.log.debug { "webrick log #{access_log.chomp}" }
|
|
117
117
|
end
|
|
118
118
|
end
|
|
119
119
|
end
|
data/lib/aspera/yaml.rb
CHANGED
|
@@ -15,7 +15,7 @@ module Aspera
|
|
|
15
15
|
return duplicate_keys unless node.respond_to?(:children)
|
|
16
16
|
if node.is_a?(Psych::Nodes::Mapping)
|
|
17
17
|
counts = Hash.new(0)
|
|
18
|
-
key_nodes = Hash.new{ |h, k| h[k] = []}
|
|
18
|
+
key_nodes = Hash.new { |h, k| h[k] = [] }
|
|
19
19
|
node.children.each_slice(2) do |key_node, value_node|
|
|
20
20
|
if key_node&.value
|
|
21
21
|
counts[key_node.value] += 1
|
|
@@ -26,11 +26,11 @@ module Aspera
|
|
|
26
26
|
counts.each do |key_str, count|
|
|
27
27
|
next if count <= 1
|
|
28
28
|
path = (parent_path + [key_str]).join('.')
|
|
29
|
-
occurrences = key_nodes[key_str].map{ |kn| kn.start_line ? kn.start_line + 1 : 'unknown'}.join(', ')
|
|
29
|
+
occurrences = key_nodes[key_str].map { |kn| kn.start_line ? kn.start_line + 1 : 'unknown' }.join(', ')
|
|
30
30
|
duplicate_keys << "#{path}: #{occurrences}"
|
|
31
31
|
end
|
|
32
32
|
else
|
|
33
|
-
node.children.to_a.each{ |child| find_duplicate_keys(child, parent_path, duplicate_keys)}
|
|
33
|
+
node.children.to_a.each { |child| find_duplicate_keys(child, parent_path, duplicate_keys) }
|
|
34
34
|
end
|
|
35
35
|
duplicate_keys
|
|
36
36
|
end
|
|
@@ -43,7 +43,7 @@ module Aspera
|
|
|
43
43
|
# @raise [RuntimeError] If duplicate keys are found
|
|
44
44
|
def safe_load(yaml)
|
|
45
45
|
duplicate_keys = find_duplicate_keys(Psych.parse_stream(yaml))
|
|
46
|
-
Aspera.assert(duplicate_keys.empty?){"Duplicate keys: #{duplicate_keys.join('; ')}"}
|
|
46
|
+
Aspera.assert(duplicate_keys.empty?) { "Duplicate keys: #{duplicate_keys.join('; ')}" }
|
|
47
47
|
YAML.safe_load(yaml, permitted_classes: [Time, Date, Symbol])
|
|
48
48
|
end
|
|
49
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.27.
|
|
4
|
+
version: 4.27.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Laurent Martin
|
|
@@ -317,6 +317,7 @@ files:
|
|
|
317
317
|
- CHANGELOG.md
|
|
318
318
|
- CONTRIBUTING.md
|
|
319
319
|
- README.md
|
|
320
|
+
- TODO.md
|
|
320
321
|
- bin/ascli
|
|
321
322
|
- bin/asession
|
|
322
323
|
- docs/README.md
|
|
@@ -357,6 +358,7 @@ files:
|
|
|
357
358
|
- lib/aspera/cli/info.rb
|
|
358
359
|
- lib/aspera/cli/mailer.rb
|
|
359
360
|
- lib/aspera/cli/mcp_tool.rb
|
|
361
|
+
- lib/aspera/cli/option_declarator.rb
|
|
360
362
|
- lib/aspera/cli/options.schema.yaml
|
|
361
363
|
- lib/aspera/cli/parser.rb
|
|
362
364
|
- lib/aspera/cli/plugins/alee.rb
|
|
@@ -368,7 +370,6 @@ files:
|
|
|
368
370
|
- lib/aspera/cli/plugins/console.rb
|
|
369
371
|
- lib/aspera/cli/plugins/cos.rb
|
|
370
372
|
- lib/aspera/cli/plugins/factory.rb
|
|
371
|
-
- lib/aspera/cli/plugins/faspex.rb
|
|
372
373
|
- lib/aspera/cli/plugins/faspex5.rb
|
|
373
374
|
- lib/aspera/cli/plugins/faspio.rb
|
|
374
375
|
- lib/aspera/cli/plugins/httpgw.rb
|
|
@@ -420,6 +421,9 @@ files:
|
|
|
420
421
|
- lib/aspera/keychain/factory.rb
|
|
421
422
|
- lib/aspera/keychain/hashicorp_vault.rb
|
|
422
423
|
- lib/aspera/keychain/macos_security.rb
|
|
424
|
+
- lib/aspera/keychain/one_password_api.rb
|
|
425
|
+
- lib/aspera/keychain/one_password_base.rb
|
|
426
|
+
- lib/aspera/keychain/one_password_cli.rb
|
|
423
427
|
- lib/aspera/line_logger.rb
|
|
424
428
|
- lib/aspera/link_header.rb
|
|
425
429
|
- lib/aspera/log.rb
|
|
@@ -455,7 +459,10 @@ files:
|
|
|
455
459
|
- lib/aspera/rest_errors_aspera.rb
|
|
456
460
|
- lib/aspera/rest_list.rb
|
|
457
461
|
- lib/aspera/schema/IBM Aspera Faspex API-5.0-enhanced.yaml
|
|
462
|
+
- lib/aspera/schema/IBM Aspera Node API-4.4.6.yaml
|
|
463
|
+
- lib/aspera/schema/IBM Aspera faspio Gateway API-1.0.0.yaml
|
|
458
464
|
- lib/aspera/schema/IBM Aspera on Cloud API-0.2.6-enhanced.yaml
|
|
465
|
+
- lib/aspera/schema/IBM_Aspera_Shares.yaml
|
|
459
466
|
- lib/aspera/schema/async_tables.yaml
|
|
460
467
|
- lib/aspera/schema/documentation.rb
|
|
461
468
|
- lib/aspera/schema/reader.rb
|
|
@@ -476,7 +483,6 @@ files:
|
|
|
476
483
|
- lib/aspera/transfer/resumer.rb
|
|
477
484
|
- lib/aspera/transfer/spec.rb
|
|
478
485
|
- lib/aspera/transfer/spec.schema.yaml
|
|
479
|
-
- lib/aspera/transfer/uri.rb
|
|
480
486
|
- lib/aspera/uri_reader.rb
|
|
481
487
|
- lib/aspera/web_auth.rb
|
|
482
488
|
- lib/aspera/web_server_simple.rb
|
|
@@ -508,7 +514,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
508
514
|
version: '0'
|
|
509
515
|
requirements:
|
|
510
516
|
- Read the manual for any requirement
|
|
511
|
-
rubygems_version: 4.0.
|
|
517
|
+
rubygems_version: 4.0.20
|
|
512
518
|
specification_version: 4
|
|
513
519
|
summary: 'Execute actions using command line on IBM Aspera Server products: Aspera
|
|
514
520
|
on Cloud, Faspex, Shares, Node, Console, Orchestrator, High Speed Transfer Server'
|
metadata.gz.sig
CHANGED
|
Binary file
|