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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'aspera/cli/extended_value'
|
|
4
|
+
require 'aspera/dot_container'
|
|
4
5
|
require 'aspera/cli/version'
|
|
5
6
|
require 'aspera/cli/info'
|
|
6
7
|
require 'aspera/log'
|
|
@@ -17,10 +18,12 @@ module Aspera
|
|
|
17
18
|
class PresetManager
|
|
18
19
|
# Reserved keys in the YAML config file
|
|
19
20
|
module Key
|
|
20
|
-
CONFIG
|
|
21
|
-
VERSION
|
|
22
|
-
DEFAULTS
|
|
23
|
-
GLOBAL
|
|
21
|
+
CONFIG = 'config'
|
|
22
|
+
VERSION = 'version'
|
|
23
|
+
DEFAULTS = 'default'
|
|
24
|
+
GLOBAL = 'global_common_defaults'
|
|
25
|
+
# Prefix for comment/meta keys ignored during preset parsing (e.g. _comment)
|
|
26
|
+
META_PREFIX = '_'
|
|
24
27
|
end
|
|
25
28
|
|
|
26
29
|
GLOBAL_DEFAULT_KEYWORD = 'GLOBAL'
|
|
@@ -55,13 +58,13 @@ module Aspera
|
|
|
55
58
|
# Read and validate the YAML config file.
|
|
56
59
|
# Sets @config_presets and @checksum_on_disk.
|
|
57
60
|
def read_config_file
|
|
58
|
-
Log.log.debug{"config file is: #{@config_file}".red}
|
|
61
|
+
Log.log.debug { "config file is: #{@config_file}".red }
|
|
59
62
|
if File.exist?(@config_file)
|
|
60
|
-
Log.log.debug{"loading #{@config_file}"}
|
|
63
|
+
Log.log.debug { "loading #{@config_file}" }
|
|
61
64
|
@config_presets = Yaml.safe_load(File.read(@config_file))
|
|
62
65
|
@checksum_on_disk = checksum
|
|
63
66
|
else
|
|
64
|
-
Log.log.warn{"No config file found. New configuration file: #{@config_file}"}
|
|
67
|
+
Log.log.warn { "No config file found. New configuration file: #{@config_file}" }
|
|
65
68
|
@config_presets = {Key::CONFIG => {Key::VERSION => 'new file'}}
|
|
66
69
|
# @checksum_on_disk remains nil: will be saved on first write
|
|
67
70
|
end
|
|
@@ -70,11 +73,11 @@ module Aspera
|
|
|
70
73
|
Log.log.error('YAML error in config file')
|
|
71
74
|
raise e
|
|
72
75
|
rescue StandardError => e
|
|
73
|
-
Log.log.debug{"-> #{e.class.name} : #{e}"}
|
|
76
|
+
Log.log.debug { "-> #{e.class.name} : #{e}" }
|
|
74
77
|
if File.exist?(@config_file)
|
|
75
78
|
new_name = "#{@config_file}.pre#{Cli::VERSION}.manual_conversion_needed"
|
|
76
79
|
File.rename(@config_file, new_name)
|
|
77
|
-
Log.log.warn{"Renamed config file to #{new_name}."}
|
|
80
|
+
Log.log.warn { "Renamed config file to #{new_name}." }
|
|
78
81
|
Log.log.warn('Manual Conversion is required. Next time, a new empty file will be created.')
|
|
79
82
|
end
|
|
80
83
|
raise Cli::Error, e.to_s
|
|
@@ -83,13 +86,13 @@ module Aspera
|
|
|
83
86
|
# Save to disk only if content changed since last load/save.
|
|
84
87
|
# @return [Boolean] true if actually written
|
|
85
88
|
def save_if_needed
|
|
86
|
-
Aspera.assert(!@config_presets.nil?, type: Cli::Error){'no configuration loaded'}
|
|
89
|
+
Aspera.assert(!@config_presets.nil?, type: Cli::Error) { 'no configuration loaded' }
|
|
87
90
|
current = checksum
|
|
88
91
|
return false if @checksum_on_disk.eql?(current)
|
|
89
92
|
FileUtils.mkdir_p(File.dirname(@config_file))
|
|
90
93
|
Environment.restrict_file_access(File.dirname(@config_file))
|
|
91
|
-
Log.log.info{"Saving config file: #{@config_file}"}
|
|
92
|
-
Environment.write_file_restricted(@config_file, force: true){@config_presets.to_yaml}
|
|
94
|
+
Log.log.info { "Saving config file: #{@config_file}" }
|
|
95
|
+
Environment.write_file_restricted(@config_file, force: true) { @config_presets.to_yaml }
|
|
93
96
|
@checksum_on_disk = current
|
|
94
97
|
true
|
|
95
98
|
end
|
|
@@ -103,7 +106,7 @@ module Aspera
|
|
|
103
106
|
Aspera.assert(!@config_presets.nil?, 'config_presets shall be defined')
|
|
104
107
|
return unless @use_plugin_defaults
|
|
105
108
|
return unless @config_presets.key?(Key::DEFAULTS)
|
|
106
|
-
Aspera.assert_type(@config_presets[Key::DEFAULTS], Hash){'default section'}
|
|
109
|
+
Aspera.assert_type(@config_presets[Key::DEFAULTS], Hash) { 'default section' }
|
|
107
110
|
return unless @config_presets[Key::DEFAULTS].key?(plugin_name_sym.to_s)
|
|
108
111
|
default_name = @config_presets[Key::DEFAULTS][plugin_name_sym.to_s]
|
|
109
112
|
unless @config_presets.key?(default_name)
|
|
@@ -115,7 +118,7 @@ module Aspera
|
|
|
115
118
|
end
|
|
116
119
|
raise Cli::Error, "No such preset: #{default_name}"
|
|
117
120
|
end
|
|
118
|
-
Aspera.assert_type(@config_presets[default_name], Hash, type: Cli::Error){'preset type'}
|
|
121
|
+
Aspera.assert_type(@config_presets[default_name], Hash, type: Cli::Error) { 'preset type' }
|
|
119
122
|
default_name
|
|
120
123
|
end
|
|
121
124
|
|
|
@@ -124,38 +127,62 @@ module Aspera
|
|
|
124
127
|
# @param config_name [String]
|
|
125
128
|
# @param include_path [Array] guard against include loops
|
|
126
129
|
def by_name(config_name, include_path = [])
|
|
127
|
-
Aspera.assert(!include_path.include?(config_name), type: Cli::Error){'loop in include'}
|
|
130
|
+
Aspera.assert(!include_path.include?(config_name), type: Cli::Error) { 'loop in include' }
|
|
128
131
|
include_path = include_path.clone
|
|
129
132
|
current = @config_presets
|
|
130
133
|
config_name.split(PRESET_DIG_SEPARATOR).each do |name|
|
|
131
|
-
Aspera.assert_type(current, Hash, type: Cli::Error){"sub key: #{include_path}"}
|
|
134
|
+
Aspera.assert_type(current, Hash, type: Cli::Error) { "sub key: #{include_path}" }
|
|
132
135
|
include_path.push(name)
|
|
133
136
|
current = current[name]
|
|
134
|
-
Aspera.assert(!current.nil?, type: Cli::Error){"Unknown config preset: #{include_path}"}
|
|
137
|
+
Aspera.assert(!current.nil?, type: Cli::Error) { "Unknown config preset: #{include_path}" }
|
|
135
138
|
end
|
|
136
139
|
current = self.class.deep_clone(current) unless current.is_a?(String)
|
|
140
|
+
current.delete_if { |k, _| k.to_s.start_with?(Key::META_PREFIX) } if current.is_a?(Hash)
|
|
137
141
|
ExtendedValue.instance.evaluate(current, context: 'preset')
|
|
138
142
|
end
|
|
139
143
|
|
|
140
144
|
# Set a single key in a preset hash (creates the preset if absent).
|
|
145
|
+
# If param_name contains dots, it is treated as a dot-path and deep-merged into the preset.
|
|
146
|
+
# If param_value is nil, the key is deleted instead.
|
|
141
147
|
def set_key(preset, param_name, param_value)
|
|
142
|
-
Aspera.assert_type(param_name, String, Symbol){'parameter'}
|
|
148
|
+
Aspera.assert_type(param_name, String, Symbol) { 'parameter' }
|
|
143
149
|
param_name = param_name.to_s
|
|
144
150
|
selected = @config_presets[preset]
|
|
145
151
|
if selected.nil?
|
|
146
|
-
Log.log.debug{"Unknown preset name: #{preset}, initializing"}
|
|
152
|
+
Log.log.debug { "Unknown preset name: #{preset}, initializing" }
|
|
147
153
|
selected = @config_presets[preset] = {}
|
|
148
154
|
end
|
|
149
|
-
Aspera.assert_type(selected, Hash){"#{preset}.#{param_name}"}
|
|
150
|
-
if
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
155
|
+
Aspera.assert_type(selected, Hash) { "#{preset}.#{param_name}" }
|
|
156
|
+
if param_name.include?(DotContainer::SEPARATOR)
|
|
157
|
+
keys = param_name.split(DotContainer::SEPARATOR)
|
|
158
|
+
# Navigate to the parent hash
|
|
159
|
+
parent = keys[0..-2].reduce(selected) do |h, k|
|
|
160
|
+
break nil unless h.is_a?(Hash)
|
|
161
|
+
h[k]
|
|
154
162
|
end
|
|
155
|
-
|
|
163
|
+
if param_value.nil?
|
|
164
|
+
parent&.delete(keys.last)
|
|
165
|
+
Log.log.info("Deleted: #{preset}: #{param_name}")
|
|
166
|
+
else
|
|
167
|
+
# dot-path: build nested hash and deep-merge into existing preset
|
|
168
|
+
nested = DotContainer.dotted_to_container(keys, param_value)
|
|
169
|
+
self.class.deep_merge!(selected, nested)
|
|
170
|
+
Log.log.info("Updated: #{preset}: #{param_name} <- #{param_value}")
|
|
171
|
+
end
|
|
172
|
+
elsif param_value.nil?
|
|
173
|
+
selected.delete(param_name)
|
|
174
|
+
Log.log.info("Deleted: #{preset}: #{param_name}")
|
|
175
|
+
else
|
|
176
|
+
if selected.key?(param_name)
|
|
177
|
+
if selected[param_name].eql?(param_value)
|
|
178
|
+
Log.log.warn { "keeping same value for #{preset}: #{param_name}: #{param_value}" }
|
|
179
|
+
return
|
|
180
|
+
end
|
|
181
|
+
Log.log.warn { "overwriting value for #{param_name}: #{selected[param_name]}" }
|
|
182
|
+
end
|
|
183
|
+
selected[param_name] = param_value
|
|
184
|
+
Log.log.info("Updated: #{preset}: #{param_name} <- #{param_value}")
|
|
156
185
|
end
|
|
157
|
-
selected[param_name] = param_value
|
|
158
|
-
Log.log.info("Updated: #{preset}: #{param_name} <- #{param_value}")
|
|
159
186
|
nil
|
|
160
187
|
end
|
|
161
188
|
|
|
@@ -192,7 +219,7 @@ module Aspera
|
|
|
192
219
|
# @return [Hash, nil]
|
|
193
220
|
def lookup_preset(url:, username:)
|
|
194
221
|
url = canonical_url(url)
|
|
195
|
-
Log.log.debug{"Lookup preset for #{username}@#{url}"}
|
|
222
|
+
Log.log.debug { "Lookup preset for #{username}@#{url}" }
|
|
196
223
|
@config_presets.each_value do |v|
|
|
197
224
|
next unless v.is_a?(Hash)
|
|
198
225
|
conf_url = v['url'].is_a?(String) ? canonical_url(v['url']) : nil
|
|
@@ -209,6 +236,21 @@ module Aspera
|
|
|
209
236
|
def deep_clone(val)
|
|
210
237
|
Marshal.load(Marshal.dump(val))
|
|
211
238
|
end
|
|
239
|
+
|
|
240
|
+
# Recursively merge src into dst in place (dst wins on scalar conflicts).
|
|
241
|
+
# @param dst [Hash] destination (modified in place)
|
|
242
|
+
# @param src [Hash] source
|
|
243
|
+
# @return [Hash] dst
|
|
244
|
+
def deep_merge!(dst, src)
|
|
245
|
+
src.each do |k, v|
|
|
246
|
+
if dst.key?(k) && dst[k].is_a?(Hash) && v.is_a?(Hash)
|
|
247
|
+
deep_merge!(dst[k], v)
|
|
248
|
+
else
|
|
249
|
+
dst[k] = v
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
dst
|
|
253
|
+
end
|
|
212
254
|
end
|
|
213
255
|
|
|
214
256
|
private
|
|
@@ -221,11 +263,11 @@ module Aspera
|
|
|
221
263
|
# Structural validation + compatibility fixes on @config_presets
|
|
222
264
|
def validate_config_presets!
|
|
223
265
|
Log.dump(:available_presets, @config_presets, level: :trace1)
|
|
224
|
-
Aspera.assert_type(@config_presets, Hash){'config file YAML'}
|
|
225
|
-
Aspera.assert(@config_presets.key?(Key::CONFIG)){"Cannot find key: #{Key::CONFIG}"}
|
|
266
|
+
Aspera.assert_type(@config_presets, Hash) { 'config file YAML' }
|
|
267
|
+
Aspera.assert(@config_presets.key?(Key::CONFIG)) { "Cannot find key: #{Key::CONFIG}" }
|
|
226
268
|
version = @config_presets[Key::CONFIG][Key::VERSION]
|
|
227
|
-
Aspera.assert(!version.nil?, type: Cli::Error){'No version found in config section.'}
|
|
228
|
-
Log.log.debug{"conf version: #{version}"}
|
|
269
|
+
Aspera.assert(!version.nil?, type: Cli::Error) { 'No version found in config section.' }
|
|
270
|
+
Log.log.debug { "conf version: #{version}" }
|
|
229
271
|
# Fix bug in 4.4 (creating key "true" in "default" preset)
|
|
230
272
|
@config_presets[Key::DEFAULTS].delete(true) if @config_presets[Key::DEFAULTS].is_a?(Hash)
|
|
231
273
|
# Stamp with current version
|
data/lib/aspera/cli/result.rb
CHANGED
|
@@ -56,7 +56,7 @@ module Aspera
|
|
|
56
56
|
formatter.display_message(:data, formatter.special_format('null (no image)'))
|
|
57
57
|
return
|
|
58
58
|
end
|
|
59
|
-
Aspera.assert_type(@data, String){'image: URL or blob'}
|
|
59
|
+
Aspera.assert_type(@data, String) { 'image: URL or blob' }
|
|
60
60
|
# Check if URL
|
|
61
61
|
data =
|
|
62
62
|
begin
|
|
@@ -83,7 +83,7 @@ module Aspera
|
|
|
83
83
|
formatter.display_message(:data, Preview::Terminal.build(data, **formatter.image_options))
|
|
84
84
|
end
|
|
85
85
|
else
|
|
86
|
-
Aspera.error_unexpected_value(formatter.format_type){'format'}
|
|
86
|
+
Aspera.error_unexpected_value(formatter.format_type) { 'format' }
|
|
87
87
|
end
|
|
88
88
|
end
|
|
89
89
|
end
|
|
@@ -130,7 +130,7 @@ module Aspera
|
|
|
130
130
|
# Status result (success, complete, etc.)
|
|
131
131
|
class Status < Result
|
|
132
132
|
def initialize(data)
|
|
133
|
-
Aspera.assert_type(data, String){'status result data'}
|
|
133
|
+
Aspera.assert_type(data, String) { 'status result data' }
|
|
134
134
|
super(data: data)
|
|
135
135
|
end
|
|
136
136
|
|
|
@@ -157,7 +157,7 @@ module Aspera
|
|
|
157
157
|
# Text result
|
|
158
158
|
class Text < Result
|
|
159
159
|
def initialize(data)
|
|
160
|
-
Aspera.assert_type(data, String, Integer, Symbol, type: ArgumentError){'text result data'}
|
|
160
|
+
Aspera.assert_type(data, String, Integer, Symbol, type: ArgumentError) { 'text result data' }
|
|
161
161
|
super(data: data)
|
|
162
162
|
end
|
|
163
163
|
|
|
@@ -185,7 +185,7 @@ module Aspera
|
|
|
185
185
|
# Image result (URL or blob)
|
|
186
186
|
class Image < Result
|
|
187
187
|
def initialize(data)
|
|
188
|
-
Aspera.assert_type(data, String, NilClass){'image result data'}
|
|
188
|
+
Aspera.assert_type(data, String, NilClass) { 'image result data' }
|
|
189
189
|
super(data: data)
|
|
190
190
|
end
|
|
191
191
|
|
|
@@ -199,7 +199,7 @@ module Aspera
|
|
|
199
199
|
# Single object result (Hash)
|
|
200
200
|
class SingleObject < Result
|
|
201
201
|
def initialize(data, fields: nil)
|
|
202
|
-
Aspera.assert_type(data, Hash){'single object result data'}
|
|
202
|
+
Aspera.assert_type(data, Hash) { 'single object result data' }
|
|
203
203
|
super(data: data, fields: fields)
|
|
204
204
|
end
|
|
205
205
|
|
|
@@ -214,7 +214,7 @@ module Aspera
|
|
|
214
214
|
# Create an Image result and format it
|
|
215
215
|
Image.new(@data[fields.first]).format(formatter)
|
|
216
216
|
when :table, :csv
|
|
217
|
-
Aspera.assert_type(@data, Hash){'result'}
|
|
217
|
+
Aspera.assert_type(@data, Hash) { 'result' }
|
|
218
218
|
if @data.empty?
|
|
219
219
|
formatter.display_message(:data, formatter.special_format('empty dict'))
|
|
220
220
|
else
|
|
@@ -236,8 +236,8 @@ module Aspera
|
|
|
236
236
|
# @param fields [Array<String>, Proc, nil] Fields to display in table/csv format
|
|
237
237
|
# @param total [Integer, nil] Total number of items available (for pagination display)
|
|
238
238
|
def initialize(data, fields: nil, total: nil)
|
|
239
|
-
Aspera.assert_array_all(data, Hash, type: ArgumentError){'object list result data'}
|
|
240
|
-
Aspera.assert_type(total, Integer, NilClass){'total'}
|
|
239
|
+
Aspera.assert_array_all(data, Hash, type: ArgumentError) { 'object list result data' }
|
|
240
|
+
Aspera.assert_type(total, Integer, NilClass) { 'total' }
|
|
241
241
|
super(data: data, fields: fields)
|
|
242
242
|
@total = total
|
|
243
243
|
end
|
|
@@ -250,8 +250,8 @@ module Aspera
|
|
|
250
250
|
Aspera.assert(@data.length == 1, 'image display requires a single result', type: Cli::BadArgument)
|
|
251
251
|
SingleObject.new(@data.first).format(formatter)
|
|
252
252
|
when :table, :csv
|
|
253
|
-
Aspera.assert_array_all(@data, Hash){'result'}
|
|
254
|
-
data = formatter.flat_hash? ? @data.map{ |obj| DotContainer.new(obj).to_dotted} : @data
|
|
253
|
+
Aspera.assert_array_all(@data, Hash) { 'result' }
|
|
254
|
+
data = formatter.flat_hash? ? @data.map { |obj| DotContainer.new(obj).to_dotted } : @data
|
|
255
255
|
formatter.display_table(data, formatter.compute_fields(data, @fields), single: false)
|
|
256
256
|
else
|
|
257
257
|
super
|
|
@@ -264,8 +264,8 @@ module Aspera
|
|
|
264
264
|
attr_reader :name
|
|
265
265
|
|
|
266
266
|
def initialize(data, name: 'id')
|
|
267
|
-
Aspera.assert_type(data, Array){'value list result data'}
|
|
268
|
-
Aspera.assert_type(name, String){'value list name'}
|
|
267
|
+
Aspera.assert_type(data, Array) { 'value list result data' }
|
|
268
|
+
Aspera.assert_type(name, String) { 'value list name' }
|
|
269
269
|
super(data: data)
|
|
270
270
|
@name = name
|
|
271
271
|
end
|
|
@@ -273,7 +273,7 @@ module Aspera
|
|
|
273
273
|
def format(formatter)
|
|
274
274
|
case formatter.format_type
|
|
275
275
|
when :table, :csv
|
|
276
|
-
formatter.display_table(@data.map{ |i| {@name => i}}, [@name])
|
|
276
|
+
formatter.display_table(@data.map { |i| {@name => i} }, [@name])
|
|
277
277
|
when :text
|
|
278
278
|
formatter.display_message(:data, @data.join("\n"))
|
|
279
279
|
when :ruby
|
|
@@ -314,6 +314,8 @@ module Aspera
|
|
|
314
314
|
result = res if res.is_a?(Hash)
|
|
315
315
|
# TODO: remove when faspio gw api fixes this
|
|
316
316
|
result = res.first if res.is_a?(Array) && res.first.is_a?(Hash)
|
|
317
|
+
# Ensure the id_result key is always present even when the API response uses a different key name
|
|
318
|
+
result[id_result] = item unless result.key?(id_result)
|
|
317
319
|
result['status'] = "#{command}#{'e' unless command.to_s.end_with?('e')}d".gsub(/yed$/, 'ied')
|
|
318
320
|
rescue StandardError => e
|
|
319
321
|
raise e if bfail
|
|
@@ -347,11 +349,11 @@ module Aspera
|
|
|
347
349
|
unsupported_types = all_types - scalar_types
|
|
348
350
|
return ValueList.new(data, name: 'list') if unsupported_types.empty?
|
|
349
351
|
|
|
350
|
-
Aspera.error_unexpected_value(unsupported_types){'list item types'}
|
|
352
|
+
Aspera.error_unexpected_value(unsupported_types) { 'list item types' }
|
|
351
353
|
when String, Integer, Symbol
|
|
352
354
|
Text.new(data)
|
|
353
355
|
else
|
|
354
|
-
Aspera.error_unexpected_value(data.class.name){'result type'}
|
|
356
|
+
Aspera.error_unexpected_value(data.class.name) { 'result type' }
|
|
355
357
|
end
|
|
356
358
|
end
|
|
357
359
|
end
|
data/lib/aspera/cli/runner.rb
CHANGED
|
@@ -126,18 +126,18 @@ module Aspera
|
|
|
126
126
|
lock_port = @context.options.get_option(:lock_port)
|
|
127
127
|
if !lock_port.nil?
|
|
128
128
|
begin
|
|
129
|
-
Log.log.debug{"Opening lock port #{lock_port}"}
|
|
129
|
+
Log.log.debug { "Opening lock port #{lock_port}" }
|
|
130
130
|
@tcp_server = TCPServer.new('127.0.0.1', lock_port)
|
|
131
131
|
rescue StandardError => e
|
|
132
132
|
execute_command = false
|
|
133
|
-
Log.log.warn{"Another instance is already running (#{e.message})."}
|
|
133
|
+
Log.log.warn { "Another instance is already running (#{e.message})." }
|
|
134
134
|
end
|
|
135
135
|
end
|
|
136
136
|
pid_file = @context.options.get_option(:pid_file)
|
|
137
137
|
if !pid_file.nil?
|
|
138
138
|
File.write(pid_file, Process.pid)
|
|
139
|
-
Log.log.debug{"Wrote pid #{Process.pid} to #{pid_file}"}
|
|
140
|
-
at_exit{File.delete(pid_file)}
|
|
139
|
+
Log.log.debug { "Wrote pid #{Process.pid} to #{pid_file}" }
|
|
140
|
+
at_exit { File.delete(pid_file) }
|
|
141
141
|
end
|
|
142
142
|
begin
|
|
143
143
|
result = command_plugin.execute_action if execute_command
|
|
@@ -174,25 +174,33 @@ module Aspera
|
|
|
174
174
|
# 1- processing of error condition
|
|
175
175
|
unless exception_info.nil?
|
|
176
176
|
Log.log.warn(exception_info[:e].message) if Log.instance.logger_type.eql?(:syslog) && exception_info[:security]
|
|
177
|
-
Log.log.error{"#{exception_info[:t]}: #{exception_info[:e].message}"} unless exception_info[:e].is_a?(Cli::SchemaRequest)
|
|
178
|
-
Log.log.debug{(['Backtrace:'] + exception_info[:e].backtrace).join("\n")} if exception_info[:debug]
|
|
177
|
+
Log.log.error { "#{exception_info[:t]}: #{exception_info[:e].message}" } unless exception_info[:e].is_a?(Cli::SchemaRequest)
|
|
178
|
+
Log.log.debug { (['Backtrace:'] + exception_info[:e].backtrace).join("\n") } if exception_info[:debug]
|
|
179
179
|
@context.formatter.display_message(:error, 'Use option -h to get help.') if exception_info[:usage]
|
|
180
180
|
Hints.hint_for(exception_info[:e], @context.formatter)
|
|
181
181
|
if exception_info[:e].is_a?(Cli::SchemaRequest)
|
|
182
|
-
Log.log.info{"#{exception_info[:t]}: #{exception_info[:e].message}"}
|
|
182
|
+
Log.log.info { "#{exception_info[:t]}: #{exception_info[:e].message}" }
|
|
183
183
|
schema_path = exception_info[:e].path
|
|
184
184
|
if schema_path.nil?
|
|
185
|
-
Log.log.warn{'Sorry, no schema provided yet. Please refer to the manual or API.'}
|
|
185
|
+
Log.log.warn { 'Sorry, no schema provided yet. Please refer to the manual or API.' }
|
|
186
186
|
else
|
|
187
|
-
|
|
188
|
-
|
|
187
|
+
reader = Schema::Registry.instance.reader(schema_path)
|
|
188
|
+
rows = reader.to_rows.map do |row|
|
|
189
|
+
if row.key?('enum')
|
|
190
|
+
row = row.dup
|
|
191
|
+
row['type'] = 'enum'
|
|
192
|
+
row['description'] = "#{row['description']}\nAllowed: #{row['enum'].join(', ')}"
|
|
193
|
+
end
|
|
194
|
+
row
|
|
195
|
+
end
|
|
196
|
+
@context.formatter.display_results(Result::ObjectList.new(rows, fields: %w[name type required description]))
|
|
189
197
|
end
|
|
190
198
|
end
|
|
191
199
|
end
|
|
192
200
|
# 2- processing of unprocessed arguments (skip when help was displayed: sub-commands are not consumed)
|
|
193
201
|
unless @option_help
|
|
194
202
|
@context.options&.final_errors&.each do |msg|
|
|
195
|
-
Log.log.error{"Argument: #{msg}"}
|
|
203
|
+
Log.log.error { "Argument: #{msg}" }
|
|
196
204
|
exception_info = {e: Exception.new(msg), t: 'UnusedArg'} if exception_info.nil?
|
|
197
205
|
end
|
|
198
206
|
end
|
|
@@ -236,7 +244,7 @@ module Aspera
|
|
|
236
244
|
when :type then Log.instance.logger_type = v.to_sym
|
|
237
245
|
when :format then Log.instance.formatter = v
|
|
238
246
|
when :secrets then SecretHider.instance.log_secrets = BoolValue.true?(v)
|
|
239
|
-
else Aspera.error_unexpected_value(k){'log sub-option (level, type, format, secrets)'}
|
|
247
|
+
else Aspera.error_unexpected_value(k) { 'log sub-option (level, type, format, secrets)' }
|
|
240
248
|
end
|
|
241
249
|
end
|
|
242
250
|
when :get
|
|
@@ -259,9 +267,9 @@ module Aspera
|
|
|
259
267
|
lines = [@context.options.help_text(banner: app_banner)]
|
|
260
268
|
if plugin.nil?
|
|
261
269
|
# Top-level: list all available plugins
|
|
262
|
-
plugin_names = Plugins::Factory.instance.plugin_list.reject{ |s| s.eql?(COMMAND_CONFIG)}.sort
|
|
270
|
+
plugin_names = Plugins::Factory.instance.plugin_list.reject { |s| s.eql?(COMMAND_CONFIG) }.sort
|
|
263
271
|
lines << "\nPLUGINS"
|
|
264
|
-
col_w = plugin_names.map{ |n| n.to_s.length}.max + 2
|
|
272
|
+
col_w = plugin_names.map { |n| n.to_s.length }.max + 2
|
|
265
273
|
plugin_names.each do |name|
|
|
266
274
|
app = Plugins::Factory.instance.plugin_class(name).application_name
|
|
267
275
|
lines << " #{name.to_s.ljust(col_w)} #{app}"
|
|
@@ -283,29 +291,42 @@ module Aspera
|
|
|
283
291
|
end
|
|
284
292
|
end
|
|
285
293
|
end
|
|
294
|
+
if cmds.none?
|
|
295
|
+
leaf_spec = registry[path]
|
|
296
|
+
leaf_spec&.arguments&.each do |arg_spec|
|
|
297
|
+
argument = arg_spec.mandatory ? "<#{arg_spec.name}>" : "[#{arg_spec.name}]"
|
|
298
|
+
argument += '...' if arg_spec.multiple
|
|
299
|
+
label += " #{argument}"
|
|
300
|
+
end
|
|
301
|
+
end
|
|
286
302
|
if cmds.any?
|
|
287
|
-
# Intermediate node: list subcommands
|
|
288
|
-
lines << "\
|
|
289
|
-
|
|
303
|
+
# Intermediate node: show current command + description, then list subcommands
|
|
304
|
+
lines << "\nCOMMAND: #{label}"
|
|
305
|
+
node_spec = path.empty? ? nil : registry[path]
|
|
306
|
+
lines << " #{node_spec.description}" if node_spec&.description
|
|
307
|
+
lines << "\n SUBCOMMANDS:"
|
|
308
|
+
col_w = cmds.keys.map { |k| k.to_s.length }.max + 2
|
|
290
309
|
cmds.each do |id, spec|
|
|
291
310
|
lines << " #{id.to_s.ljust(col_w)} #{spec.description}"
|
|
292
311
|
end
|
|
293
312
|
else
|
|
294
|
-
# Leaf node: show description + arguments
|
|
313
|
+
# Leaf node: show description + arguments.
|
|
295
314
|
spec = registry[path]
|
|
296
315
|
lines << "\nCOMMAND: #{label}"
|
|
297
316
|
lines << " #{spec.description}" if spec&.description
|
|
298
317
|
display_args = spec&.arguments || []
|
|
299
318
|
# transfer_paths commands use --sources for the file list; default is positional args (@args)
|
|
300
319
|
if spec&.transfer_paths
|
|
301
|
-
file_desc = spec.transfer_paths == :receive
|
|
302
|
-
|
|
303
|
-
|
|
320
|
+
file_desc = if spec.transfer_paths == :receive
|
|
321
|
+
"Remote path(s) to download (default --sources=#{TransferAgent::FILE_LIST_FROM_ARGS}; see also --to-folder)"
|
|
322
|
+
else
|
|
323
|
+
"Source file(s) to upload (default --sources=#{TransferAgent::FILE_LIST_FROM_ARGS}; see also --src-type, --to-folder)"
|
|
324
|
+
end
|
|
304
325
|
display_args += [ArgumentSpec.new(name: :source_file, description: file_desc, mandatory: false, multiple: true)]
|
|
305
326
|
end
|
|
306
327
|
if display_args.any?
|
|
307
328
|
lines << "\nARGUMENTS:"
|
|
308
|
-
col_w = display_args.map{ |a| a.name.to_s.length}.max + 2
|
|
329
|
+
col_w = display_args.map { |a| a.name.to_s.length }.max + 2
|
|
309
330
|
display_args.each do |arg|
|
|
310
331
|
flag = arg.mandatory ? arg.name.to_s : "[#{arg.name}]"
|
|
311
332
|
flag += '...' if arg.multiple
|
|
@@ -315,16 +336,31 @@ module Aspera
|
|
|
315
336
|
when nil then ''
|
|
316
337
|
else arg.type.name
|
|
317
338
|
end
|
|
318
|
-
hint = arg.type.
|
|
339
|
+
hint = Array(arg.type).include?(Hash) && arg.schema ? ' (schema shown below)' : ''
|
|
319
340
|
lines << " #{flag.ljust(col_w)} #{arg.description || types}#{hint}"
|
|
341
|
+
lines.concat(schema_help_lines(arg)) if Array(arg.type).include?(Hash) && arg.schema
|
|
320
342
|
end
|
|
321
343
|
end
|
|
322
|
-
lines << "\nTIP: use --query=help to list available query parameters" if spec&.query_schema
|
|
344
|
+
lines << "\nTIP: use --query=help to list available query parameters" if spec&.query_schema
|
|
323
345
|
end
|
|
324
346
|
end
|
|
325
347
|
lines.join("\n")
|
|
326
348
|
end
|
|
327
349
|
|
|
350
|
+
# Render the structure of a Hash argument's JSON schema in command help.
|
|
351
|
+
# @param arg [ArgumentSpec]
|
|
352
|
+
# @return [Array<String>]
|
|
353
|
+
def schema_help_lines(arg)
|
|
354
|
+
builder = Schema::Documentation.new(TerminalFormatter, Schema::Registry.instance.reader(arg.schema)).build
|
|
355
|
+
rows = builder.rows.reject { |row| row['type'].eql?(' ') }.map do |row|
|
|
356
|
+
builder.columns.map { |column| row[column].to_s }
|
|
357
|
+
end
|
|
358
|
+
style = {}
|
|
359
|
+
style[:border] = :unicode_round if Environment.terminal_supports_unicode?
|
|
360
|
+
table = Terminal::Table.new(headings: builder.columns, rows: rows, style: style).to_s
|
|
361
|
+
["\n SCHEMA: #{arg.name}", table.lines.map { |line| " #{line.chomp}" }.join("\n")]
|
|
362
|
+
end
|
|
363
|
+
|
|
328
364
|
# Initialize agents and options
|
|
329
365
|
# This can throw exception if there is a problem with the environment, needs to be caught by execute method
|
|
330
366
|
# @raise [StandardError] if there is a problem with the environment
|
|
@@ -335,13 +371,13 @@ module Aspera
|
|
|
335
371
|
@context.formatter = Formatter.new
|
|
336
372
|
# Create command line manager with arguments
|
|
337
373
|
@context.options = Parser.new(Info::CMD_NAME, @argv)
|
|
338
|
-
ExtendedValue.instance.on(EXTEND_ARGS){ |v| @context.options.args_as_extended(v)}
|
|
374
|
+
ExtendedValue.instance.on(EXTEND_ARGS) { |v| @context.options.args_as_extended(v) }
|
|
339
375
|
# Formatter: declare metadata (class method), then bind to the instance
|
|
340
376
|
Formatter.declare_options(@context.options)
|
|
341
377
|
@context.formatter.bind_options(@context.options)
|
|
342
378
|
# Compare $0 with expected name
|
|
343
379
|
current_prog_name = File.basename($PROGRAM_NAME)
|
|
344
|
-
Aspera.assert(current_prog_name.eql?(Info::CMD_NAME), type: :warn){"Please use '#{Info::CMD_NAME}' instead of '#{current_prog_name}'"}
|
|
380
|
+
Aspera.assert(current_prog_name.eql?(Info::CMD_NAME), type: :warn) { "Please use '#{Info::CMD_NAME}' instead of '#{current_prog_name}'" }
|
|
345
381
|
# Declare and parse global options
|
|
346
382
|
declare_global_options
|
|
347
383
|
# Bootstrap: populate context services (main_folder, persistency, presets, http_config,
|
|
@@ -351,7 +387,7 @@ module Aspera
|
|
|
351
387
|
@bootstrapper = Bootstrapper.new(@context)
|
|
352
388
|
@bootstrapper.run(
|
|
353
389
|
gem_plugins_folder: Plugins::Config.gem_plugins_folder,
|
|
354
|
-
vault_value_cb: ->(v){@context.config.vault_value(v)}
|
|
390
|
+
vault_value_cb: ->(v) { @context.config.vault_value(v) }
|
|
355
391
|
)
|
|
356
392
|
# Do not display config commands if help is asked
|
|
357
393
|
@context.man_header = false
|
|
@@ -381,7 +417,7 @@ module Aspera
|
|
|
381
417
|
#{t}#{Info::CMD_NAME} -- a command line tool for Aspera Applications (v#{Cli::VERSION})
|
|
382
418
|
|
|
383
419
|
SYNOPSIS
|
|
384
|
-
#{t}#{Info::CMD_NAME}
|
|
420
|
+
#{t}#{Info::CMD_NAME} [GLOBAL_OPTIONS] <command> [OPTIONS] [ARGS]
|
|
385
421
|
|
|
386
422
|
DESCRIPTION
|
|
387
423
|
#{t}Use Aspera application to perform operations on command line.
|
|
@@ -400,8 +436,8 @@ module Aspera
|
|
|
400
436
|
OPTIONS
|
|
401
437
|
#{t}Options begin with a '-' (minus), and value is provided on command line.
|
|
402
438
|
#{t}Special values are supported beginning with special prefix @pfx:, where pfx is one of:
|
|
403
|
-
#{t}#{ExtendedValue.instance.modifiers.join(', ')}
|
|
404
|
-
#{t}Dates format is '
|
|
439
|
+
#{t}#{ExtendedValue.instance.modifiers.reject(&:empty?).join(', ')}
|
|
440
|
+
#{t}Dates format is 'YYYY-MM-DD HH:MM:SS', or 'now' or '-<num>h'
|
|
405
441
|
|
|
406
442
|
ARGS
|
|
407
443
|
#{t}Some commands require mandatory arguments, e.g. a path.
|
|
@@ -412,12 +448,12 @@ module Aspera
|
|
|
412
448
|
# @return [nil]
|
|
413
449
|
def declare_global_options
|
|
414
450
|
Log.log.debug('declare_global_options')
|
|
415
|
-
@context.options.declare(:help, description: 'Show this message', allowed:
|
|
451
|
+
@context.options.declare(:help, description: 'Show this message', allowed: Type::NONE, short: 'h') do
|
|
416
452
|
@option_help = true
|
|
417
453
|
@context.options.help_requested = true
|
|
418
454
|
end
|
|
419
|
-
@context.options.declare(:show_config, description: 'Display parameters used for the provided action', allowed:
|
|
420
|
-
@context.options.declare(:version, description: 'Display version', allowed:
|
|
455
|
+
@context.options.declare(:show_config, description: 'Display parameters used for the provided action', allowed: Type::NONE) { @option_show_config = true }
|
|
456
|
+
@context.options.declare(:version, description: 'Display version', allowed: Type::NONE, short: 'v') { @context.formatter.display_message(:data, Cli::VERSION); Process.exit(0) } # rubocop:disable Style/Semicolon
|
|
421
457
|
@context.options.declare(
|
|
422
458
|
:ui, description: 'Method to start browser',
|
|
423
459
|
allowed: USER_INTERFACES,
|
|
@@ -431,10 +467,10 @@ module Aspera
|
|
|
431
467
|
@context.options.declare(:log_format, description: 'Log formatter', allowed: [Proc, Logger::Formatter, String], handler: {o: Log.instance, m: :formatter})
|
|
432
468
|
@context.options.declare(:logger, description: 'Logging method', allowed: Log::LOG_TYPES, handler: {o: Log.instance, m: :logger_type})
|
|
433
469
|
@context.options.declare(:log, description: 'Logging options (dot-notation: level, type, format, secrets)', handler: {o: self, m: :option_log}, schema: Schema::Registry::LOG_OPTIONS)
|
|
434
|
-
@context.options.declare(:lock_port, description: 'Prevent dual execution of a command, e.g. in cron', allowed:
|
|
435
|
-
@context.options.declare(:once_only, description: 'Process only new items (some commands)', allowed:
|
|
436
|
-
@context.options.declare(:log_secrets, description: 'Show passwords in logs', allowed:
|
|
437
|
-
@context.options.declare(:clean_temp, description: 'Cleanup temporary files on exit', allowed:
|
|
470
|
+
@context.options.declare(:lock_port, description: 'Prevent dual execution of a command, e.g. in cron', allowed: Type::INTEGER)
|
|
471
|
+
@context.options.declare(:once_only, description: 'Process only new items (some commands)', allowed: Type::BOOLEAN, default: false)
|
|
472
|
+
@context.options.declare(:log_secrets, description: 'Show passwords in logs', allowed: Type::BOOLEAN, handler: {o: SecretHider.instance, m: :log_secrets})
|
|
473
|
+
@context.options.declare(:clean_temp, description: 'Cleanup temporary files on exit', allowed: Type::BOOLEAN, handler: {o: TempFileManager.instance, m: :cleanup_on_exit})
|
|
438
474
|
@context.options.declare(:temp_folder, description: 'Temporary folder', handler: {o: TempFileManager.instance, m: :global_temp})
|
|
439
475
|
@context.options.declare(:pid_file, description: 'Write process identifier to file, delete on exit')
|
|
440
476
|
@context.options.declare(
|
|
@@ -452,10 +488,10 @@ module Aspera
|
|
|
452
488
|
# @param plugin_name_sym [Symbol] symbol for plugin name
|
|
453
489
|
# @return [Plugins::Base] the plugin instance
|
|
454
490
|
def get_plugin_instance_with_options(plugin_name_sym)
|
|
455
|
-
Log.log.debug{"get_plugin_instance_with_options(#{plugin_name_sym})"}
|
|
491
|
+
Log.log.debug { "get_plugin_instance_with_options(#{plugin_name_sym})" }
|
|
456
492
|
# Load default preset options for this plugin from config file
|
|
457
493
|
default_config_name = @context.presets.plugin_default_name(plugin_name_sym)
|
|
458
|
-
Log.log.debug{"add_plugin_default_preset:#{plugin_name_sym}:#{default_config_name}"}
|
|
494
|
+
Log.log.debug { "add_plugin_default_preset:#{plugin_name_sym}:#{default_config_name}" }
|
|
459
495
|
@context.options.add_option_preset(@context.presets.by_name(default_config_name), 'default_plugin', override: false) unless default_config_name.nil?
|
|
460
496
|
command_plugin = Plugins::Factory.instance.create(plugin_name_sym, context: @context)
|
|
461
497
|
return command_plugin
|
|
@@ -29,7 +29,7 @@ module Aspera
|
|
|
29
29
|
if secret.eql?(PRESET_MAGIC)
|
|
30
30
|
conf = @presets.lookup_preset(url: url, username: username)
|
|
31
31
|
if conf.is_a?(Hash)
|
|
32
|
-
Log.log.debug{"Found preset #{conf} with URL and username"}
|
|
32
|
+
Log.log.debug { "Found preset #{conf} with URL and username" }
|
|
33
33
|
secret = conf['password']
|
|
34
34
|
end
|
|
35
35
|
end
|