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