aspera-cli 4.21.2 → 4.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/BUGS.md +1 -1
- data/CHANGELOG.md +34 -16
- data/CONTRIBUTING.md +6 -10
- data/README.md +805 -574
- data/examples/get_proto_file.rb +1 -1
- data/lib/aspera/agent/base.rb +9 -5
- data/lib/aspera/agent/connect.rb +30 -28
- data/lib/aspera/agent/desktop.rb +29 -25
- data/lib/aspera/agent/direct.rb +137 -125
- data/lib/aspera/agent/httpgw.rb +22 -26
- data/lib/aspera/agent/node.rb +14 -11
- data/lib/aspera/agent/transferd.rb +6 -2
- data/lib/aspera/api/aoc.rb +6 -6
- data/lib/aspera/api/cos_node.rb +1 -1
- data/lib/aspera/api/httpgw.rb +7 -3
- data/lib/aspera/api/node.rb +6 -4
- data/lib/aspera/ascmd.rb +3 -3
- data/lib/aspera/ascp/installation.rb +15 -16
- data/lib/aspera/ascp/management.rb +1 -1
- data/lib/aspera/assert.rb +11 -2
- data/lib/aspera/cli/error.rb +2 -2
- data/lib/aspera/cli/extended_value.rb +38 -19
- data/lib/aspera/cli/formatter.rb +48 -48
- data/lib/aspera/cli/hints.rb +1 -1
- data/lib/aspera/cli/main.rb +190 -168
- data/lib/aspera/cli/manager.rb +15 -15
- data/lib/aspera/cli/plugin.rb +23 -20
- data/lib/aspera/cli/plugin_factory.rb +1 -1
- data/lib/aspera/cli/plugins/alee.rb +1 -1
- data/lib/aspera/cli/plugins/aoc.rb +144 -107
- data/lib/aspera/cli/plugins/ats.rb +19 -17
- data/lib/aspera/cli/plugins/config.rb +67 -83
- data/lib/aspera/cli/plugins/console.rb +5 -3
- data/lib/aspera/cli/plugins/faspex.rb +39 -35
- data/lib/aspera/cli/plugins/faspex5.rb +104 -80
- data/lib/aspera/cli/plugins/faspio.rb +13 -1
- data/lib/aspera/cli/plugins/httpgw.rb +13 -1
- data/lib/aspera/cli/plugins/node.rb +306 -179
- data/lib/aspera/cli/plugins/orchestrator.rb +34 -40
- data/lib/aspera/cli/plugins/preview.rb +3 -3
- data/lib/aspera/cli/plugins/server.rb +6 -6
- data/lib/aspera/cli/plugins/shares.rb +5 -5
- data/lib/aspera/cli/sync_actions.rb +19 -18
- data/lib/aspera/cli/transfer_agent.rb +5 -5
- data/lib/aspera/cli/transfer_progress.rb +2 -2
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/command_line_builder.rb +116 -95
- data/lib/aspera/coverage.rb +4 -3
- data/lib/aspera/environment.rb +6 -6
- data/lib/aspera/faspex_gw.rb +14 -14
- data/lib/aspera/faspex_postproc.rb +7 -6
- data/lib/aspera/hash_ext.rb +2 -2
- data/lib/aspera/json_rpc.rb +1 -1
- data/lib/aspera/keychain/encrypted_hash.rb +47 -34
- data/lib/aspera/keychain/factory.rb +41 -0
- data/lib/aspera/keychain/hashicorp_vault.rb +71 -0
- data/lib/aspera/keychain/macos_security.rb +19 -11
- data/lib/aspera/log.rb +28 -34
- data/lib/aspera/nagios.rb +6 -6
- data/lib/aspera/node_simulator.rb +8 -8
- data/lib/aspera/oauth/base.rb +8 -6
- data/lib/aspera/oauth/factory.rb +5 -6
- data/lib/aspera/oauth/url_json.rb +6 -6
- data/lib/aspera/persistency_action_once.rb +6 -4
- data/lib/aspera/persistency_folder.rb +2 -2
- data/lib/aspera/preview/generator.rb +1 -1
- data/lib/aspera/preview/options.rb +16 -16
- data/lib/aspera/preview/terminal.rb +3 -3
- data/lib/aspera/preview/utils.rb +11 -13
- data/lib/aspera/products/connect.rb +1 -1
- data/lib/aspera/products/desktop.rb +1 -1
- data/lib/aspera/products/transferd.rb +1 -1
- data/lib/aspera/proxy_auto_config.rb +2 -2
- data/lib/aspera/rest.rb +52 -43
- data/lib/aspera/rest_errors_aspera.rb +1 -1
- data/lib/aspera/secret_hider.rb +5 -5
- data/lib/aspera/ssh.rb +4 -4
- data/lib/aspera/transfer/convert.rb +29 -0
- data/lib/aspera/transfer/error_info.rb +66 -66
- data/lib/aspera/transfer/parameters.rb +13 -68
- data/lib/aspera/transfer/spec.rb +5 -6
- data/lib/aspera/transfer/spec.schema.yaml +753 -0
- data/lib/aspera/transfer/spec_doc.rb +62 -0
- data/lib/aspera/transfer/sync.rb +23 -72
- data/lib/aspera/transfer/sync_instance.schema.yaml +13 -0
- data/lib/aspera/transfer/sync_session.schema.yaml +79 -0
- data/lib/aspera/transfer/uri.rb +6 -6
- data/lib/aspera/uri_reader.rb +1 -1
- data/lib/aspera/web_auth.rb +1 -1
- data/lib/aspera/web_server_simple.rb +53 -44
- data.tar.gz.sig +1 -2
- metadata +37 -4
- metadata.gz.sig +0 -0
- data/examples/build_package.sh +0 -28
- data/lib/aspera/transfer/spec.yaml +0 -718
@@ -14,8 +14,10 @@ module Aspera
|
|
14
14
|
# Access Aspera Transfer Service
|
15
15
|
# https://developer.ibm.com/aspera/docs/ats-api-reference/creating-ats-api-keys/
|
16
16
|
class Ats < Cli::Plugin
|
17
|
+
# columns for list of cloud providers
|
17
18
|
CLOUD_TABLE = %w[id name].freeze
|
18
|
-
|
19
|
+
private_constant :CLOUD_TABLE
|
20
|
+
def initialize(**_)
|
19
21
|
super
|
20
22
|
options.declare(:ibm_api_key, 'IBM API key, see https://cloud.ibm.com/iam/apikeys')
|
21
23
|
options.declare(:instance, 'ATS instance in ibm cloud')
|
@@ -68,7 +70,7 @@ module Aspera
|
|
68
70
|
when 'ibm-s3'
|
69
71
|
server_data2 = nil
|
70
72
|
if server_data.nil?
|
71
|
-
server_data2 = @ats_api_pub.all_servers.find{|s|s['id'].eql?(params['transfer_server_id'])}
|
73
|
+
server_data2 = @ats_api_pub.all_servers.find{ |s| s['id'].eql?(params['transfer_server_id'])}
|
72
74
|
raise "no such transfer server id: #{params['transfer_server_id']}" if server_data2.nil?
|
73
75
|
else
|
74
76
|
server_data2 = @ats_api_pub.all_servers.find do |s|
|
@@ -86,15 +88,15 @@ module Aspera
|
|
86
88
|
end
|
87
89
|
end
|
88
90
|
res = ats_api_pub_v1.create('access_keys', params)
|
89
|
-
return
|
91
|
+
return Main.result_single_object(res)
|
90
92
|
# TODO : action : modify, with "PUT"
|
91
93
|
when :list
|
92
94
|
params = options.get_option(:params) || {'offset' => 0, 'max_results' => 1000}
|
93
95
|
res = ats_api_pub_v1.read('access_keys', params)
|
94
|
-
return
|
96
|
+
return Main.result_object_list(res['data'], fields: ['name', 'id', 'created.at', 'modified.at'])
|
95
97
|
when :show
|
96
98
|
res = ats_api_pub_v1.read("access_keys/#{access_key_id}")
|
97
|
-
return
|
99
|
+
return Main.result_single_object(res)
|
98
100
|
when :modify
|
99
101
|
params = value_create_modify(command: command)
|
100
102
|
params['id'] = access_key_id
|
@@ -103,13 +105,13 @@ module Aspera
|
|
103
105
|
when :entitlement
|
104
106
|
ak = ats_api_pub_v1.read("access_keys/#{access_key_id}")
|
105
107
|
api_bss = Api::Alee.new(ak['license']['entitlement_id'], ak['license']['customer_id'])
|
106
|
-
return
|
108
|
+
return Main.result_single_object(api_bss.read('entitlement'))
|
107
109
|
when :delete
|
108
110
|
ats_api_pub_v1.delete("access_keys/#{access_key_id}")
|
109
111
|
return Main.result_status("deleted #{access_key_id}")
|
110
112
|
when :node
|
111
113
|
ak_data = ats_api_pub_v1.read("access_keys/#{access_key_id}")
|
112
|
-
server_data = @ats_api_pub.all_servers.find
|
114
|
+
server_data = @ats_api_pub.all_servers.find{ |i| i['id'].start_with?(ak_data['transfer_server_id'])}
|
113
115
|
raise Cli::Error, 'no such server found' if server_data.nil?
|
114
116
|
node_url = server_data['transfer_setup_url']
|
115
117
|
api_node = Api::Node.new(
|
@@ -130,7 +132,7 @@ module Aspera
|
|
130
132
|
username: access_key_id,
|
131
133
|
password: config.lookup_secret(url: ats_url, username: access_key_id)
|
132
134
|
})
|
133
|
-
return
|
135
|
+
return Main.result_single_object(api_ak_auth.read('servers'))
|
134
136
|
else Aspera.error_unexpected_value(command)
|
135
137
|
end
|
136
138
|
end
|
@@ -139,18 +141,18 @@ module Aspera
|
|
139
141
|
command = options.get_next_command(%i[clouds list show])
|
140
142
|
case command
|
141
143
|
when :clouds
|
142
|
-
return
|
144
|
+
return Main.result_object_list(@ats_api_pub.cloud_names.map{ |k, v| CLOUD_TABLE.zip([k, v]).to_h})
|
143
145
|
when :list
|
144
|
-
return
|
146
|
+
return Main.result_object_list(@ats_api_pub.all_servers, fields: %w[id cloud region])
|
145
147
|
when :show
|
146
148
|
if options.get_option(:cloud) || options.get_option(:region)
|
147
149
|
server_data = server_by_cloud_region
|
148
150
|
else
|
149
151
|
server_id = instance_identifier
|
150
|
-
server_data = @ats_api_pub.all_servers.find
|
152
|
+
server_data = @ats_api_pub.all_servers.find{ |i| i['id'].eql?(server_id)}
|
151
153
|
raise 'no such server id' if server_data.nil?
|
152
154
|
end
|
153
|
-
return
|
155
|
+
return Main.result_single_object(server_data)
|
154
156
|
end
|
155
157
|
end
|
156
158
|
|
@@ -189,16 +191,16 @@ module Aspera
|
|
189
191
|
when :instances
|
190
192
|
instances = ats_ibm_api.read('instances')
|
191
193
|
Log.log.warn{"more instances remaining: #{instances['remaining']}"} unless instances['remaining'].to_i.eql?(0)
|
192
|
-
return
|
194
|
+
return Main.result_value_list(instances['data'], name: 'instance')
|
193
195
|
when :create
|
194
196
|
created_key = ats_ibm_api.create('api_keys', value_create_modify(command: command, default: {}))
|
195
|
-
return
|
197
|
+
return Main.result_single_object(created_key)
|
196
198
|
when :list # list known api keys in ATS (this require an api_key ...)
|
197
199
|
res = ats_ibm_api.read('api_keys', {'offset' => 0, 'max_results' => 1000})
|
198
|
-
return
|
200
|
+
return Main.result_value_list(res['data'], name: 'ats_id')
|
199
201
|
when :show # show one of api_key in ATS
|
200
202
|
res = ats_ibm_api.read("api_keys/#{concerned_id}")
|
201
|
-
return
|
203
|
+
return Main.result_single_object(res)
|
202
204
|
when :delete
|
203
205
|
ats_ibm_api.delete("api_keys/#{concerned_id}")
|
204
206
|
return Main.result_status("deleted #{concerned_id}")
|
@@ -225,7 +227,7 @@ module Aspera
|
|
225
227
|
return execute_action_api_key
|
226
228
|
when :aws_trust_policy
|
227
229
|
res = ats_api_pub_v1.read('aws/trustpolicy', {region: options.get_option(:region, mandatory: true)})
|
228
|
-
return
|
230
|
+
return Main.result_single_object(res)
|
229
231
|
else Aspera.error_unexpected_value(command)
|
230
232
|
end
|
231
233
|
end
|
@@ -13,6 +13,7 @@ require 'aspera/products/transferd'
|
|
13
13
|
require 'aspera/transfer/error_info'
|
14
14
|
require 'aspera/transfer/parameters'
|
15
15
|
require 'aspera/transfer/spec'
|
16
|
+
require 'aspera/transfer/spec_doc'
|
16
17
|
require 'aspera/keychain/macos_security'
|
17
18
|
require 'aspera/proxy_auto_config'
|
18
19
|
require 'aspera/environment'
|
@@ -39,7 +40,6 @@ module Aspera
|
|
39
40
|
ASPERA_HOME_FOLDER_NAME = '.aspera'
|
40
41
|
# default config file
|
41
42
|
DEFAULT_CONFIG_FILENAME = 'config.yaml'
|
42
|
-
DEFAULT_VAULT_FILENAME = 'vault.bin'
|
43
43
|
# reserved preset names
|
44
44
|
CONF_PRESET_CONFIG = 'config'
|
45
45
|
CONF_PRESET_VERSION = 'version'
|
@@ -76,6 +76,7 @@ module Aspera
|
|
76
76
|
# for testing only
|
77
77
|
SELF_SIGNED_CERT = OpenSSL::SSL.const_get(:enon_yfirev.to_s.upcase.reverse) # cspell: disable-line
|
78
78
|
CONF_OVERVIEW_KEYS = %w[preset parameter value].freeze
|
79
|
+
SMTP_CONF_PARAMS = %i[server tls ssl port domain username password from_name from_email].freeze
|
79
80
|
private_constant :DEFAULT_CONFIG_FILENAME,
|
80
81
|
:CONF_PRESET_CONFIG,
|
81
82
|
:CONF_PRESET_VERSION,
|
@@ -97,7 +98,8 @@ module Aspera
|
|
97
98
|
:SELF_SIGNED_CERT,
|
98
99
|
:PERSISTENCY_FOLDER,
|
99
100
|
:DEFAULT_PRIV_KEY_LENGTH,
|
100
|
-
:CONF_OVERVIEW_KEYS
|
101
|
+
:CONF_OVERVIEW_KEYS,
|
102
|
+
:SMTP_CONF_PARAMS
|
101
103
|
|
102
104
|
class << self
|
103
105
|
def generate_rsa_private_key(path:, length: DEFAULT_PRIV_KEY_LENGTH)
|
@@ -142,13 +144,13 @@ module Aspera
|
|
142
144
|
end
|
143
145
|
end
|
144
146
|
|
145
|
-
def initialize(**
|
147
|
+
def initialize(**_)
|
146
148
|
# we need to defer parsing of options until we have the config file, so we can use @extend with @preset
|
147
149
|
super
|
148
150
|
@use_plugin_defaults = true
|
149
151
|
@config_presets = nil
|
150
152
|
@config_checksum_on_disk = nil
|
151
|
-
@
|
153
|
+
@vault_instance = nil
|
152
154
|
@pac_exec = nil
|
153
155
|
@sdk_default_location = false
|
154
156
|
@option_insecure = false
|
@@ -172,8 +174,8 @@ module Aspera
|
|
172
174
|
default: self.class.default_app_main_folder(app_name: Info::CMD_NAME))
|
173
175
|
options.parse_options!
|
174
176
|
Log.log.debug{"#{Info::CMD_NAME} folder: #{@main_folder}"}
|
175
|
-
# data persistency manager, created by config plugin
|
176
|
-
@persistency = PersistencyFolder.new(File.join(@main_folder, PERSISTENCY_FOLDER))
|
177
|
+
# data persistency manager, created by config plugin, set for global object
|
178
|
+
@broker.persistency = PersistencyFolder.new(File.join(@main_folder, PERSISTENCY_FOLDER))
|
177
179
|
# set folders for plugin lookup
|
178
180
|
PluginFactory.instance.add_lookup_folder(self.class.gem_plugins_folder)
|
179
181
|
PluginFactory.instance.add_lookup_folder(File.join(@main_folder, ASPERA_PLUGINS_FOLDERNAME))
|
@@ -186,19 +188,19 @@ module Aspera
|
|
186
188
|
# read config file (set @config_presets)
|
187
189
|
read_config_file
|
188
190
|
# add preset handler (needed for smtp)
|
189
|
-
ExtendedValue.instance.set_handler(EXTEND_PRESET, lambda{|v|preset_by_name(v)})
|
190
|
-
ExtendedValue.instance.set_handler(EXTEND_VAULT, lambda{|v|vault_value(v)})
|
191
|
+
ExtendedValue.instance.set_handler(EXTEND_PRESET, lambda{ |v| preset_by_name(v)})
|
192
|
+
ExtendedValue.instance.set_handler(EXTEND_VAULT, lambda{ |v| vault_value(v)})
|
191
193
|
# load defaults before it can be overridden
|
192
194
|
add_plugin_default_preset(CONF_GLOBAL_SYM)
|
193
195
|
# vault options
|
194
196
|
options.declare(:secret, 'Secret for access keys')
|
195
|
-
options.declare(:vault, 'Vault for secrets', types: Hash)
|
197
|
+
options.declare(:vault, 'Vault for secrets', types: Hash, default: {})
|
196
198
|
options.declare(:vault_password, 'Vault password')
|
197
199
|
options.parse_options!
|
198
200
|
# declare generic plugin options only after handlers are declared
|
199
201
|
Plugin.declare_generic_options(options)
|
200
202
|
# configuration options
|
201
|
-
options.declare(:no_default, 'Do not load default configuration for plugin', values: :none, short: 'N')
|
203
|
+
options.declare(:no_default, 'Do not load default configuration for plugin', values: :none, short: 'N'){@use_plugin_defaults = false}
|
202
204
|
options.declare(:preset, 'Load the named option preset from current config file', short: 'P', handler: {o: self, m: :option_preset})
|
203
205
|
options.declare(:version_check_days, 'Period in days to check new version (zero to disable)', coerce: Integer, default: DEFAULT_CHECK_NEW_VERSION_DAYS)
|
204
206
|
options.declare(:plugin_folder, 'Folder where to find additional plugins', handler: {o: self, m: :option_plugin_folder})
|
@@ -261,8 +263,8 @@ module Aspera
|
|
261
263
|
end
|
262
264
|
RestParameters.instance.user_agent = Info::CMD_NAME
|
263
265
|
RestParameters.instance.progress_bar = @progress_bar
|
264
|
-
RestParameters.instance.session_cb = lambda{|http_session|update_http_session(http_session)}
|
265
|
-
@option_http_options.keys.select{|i|RestParameters.instance.respond_to?(i)}.each do |k|
|
266
|
+
RestParameters.instance.session_cb = lambda{ |http_session| update_http_session(http_session)}
|
267
|
+
@option_http_options.keys.select{ |i| RestParameters.instance.respond_to?(i)}.each do |k|
|
266
268
|
method = "#{k}=".to_sym
|
267
269
|
RestParameters.instance.send(method, @option_http_options[k])
|
268
270
|
@option_http_options.delete(k)
|
@@ -299,7 +301,7 @@ module Aspera
|
|
299
301
|
paths_to_add = [OpenSSL::X509::DEFAULT_CERT_DIR]
|
300
302
|
# JRuby cert file seems not to be PEM
|
301
303
|
paths_to_add.push(OpenSSL::X509::DEFAULT_CERT_FILE) unless defined?(JRUBY_VERSION)
|
302
|
-
paths_to_add.select!{|f|File.exist?(f)}
|
304
|
+
paths_to_add.select!{ |f| File.exist?(f)}
|
303
305
|
elsif File.file?(path)
|
304
306
|
@certificate_store.add_file(path)
|
305
307
|
elsif File.directory?(path)
|
@@ -311,8 +313,8 @@ module Aspera
|
|
311
313
|
pp = [File.realpath(p)]
|
312
314
|
if File.directory?(p)
|
313
315
|
pp = Dir.entries(p)
|
314
|
-
.map{|e|File.realpath(File.join(p, e))}
|
315
|
-
.select{|entry|File.file?(entry)}
|
316
|
+
.map{ |e| File.realpath(File.join(p, e))}
|
317
|
+
.select{ |entry| File.file?(entry)}
|
316
318
|
end
|
317
319
|
@certificate_paths.concat(pp)
|
318
320
|
end
|
@@ -519,7 +521,7 @@ module Aspera
|
|
519
521
|
Aspera.assert_values(value.class, [String, Array]){'plugin folder'}
|
520
522
|
value = [value] if value.is_a?(String)
|
521
523
|
Aspera.assert(value.all?(String)){'plugin folder'}
|
522
|
-
value.each{|f|PluginFactory.instance.add_lookup_folder(f)}
|
524
|
+
value.each{ |f| PluginFactory.instance.add_lookup_folder(f)}
|
523
525
|
end
|
524
526
|
|
525
527
|
def option_plugin_folder
|
@@ -549,7 +551,7 @@ module Aspera
|
|
549
551
|
# files search for configuration, by default the one given by user
|
550
552
|
search_files = [@option_config_file]
|
551
553
|
# find first existing file (or nil)
|
552
|
-
conf_file_to_load = search_files.find{|f| File.exist?(f)}
|
554
|
+
conf_file_to_load = search_files.find{ |f| File.exist?(f)}
|
553
555
|
# if no file found, create default config
|
554
556
|
if conf_file_to_load.nil?
|
555
557
|
Log.log.warn{"No config file found. New configuration file: #{@option_config_file}"}
|
@@ -632,7 +634,7 @@ module Aspera
|
|
632
634
|
found_apps.push({product: plugin_name_sym, name: app_name, url: app_url, version: 'unknown'}.merge(detection_info))
|
633
635
|
end
|
634
636
|
raise "No known application found at #{app_url}" if found_apps.empty?
|
635
|
-
Aspera.assert(found_apps.all?{|a|a.keys.all?(Symbol)})
|
637
|
+
Aspera.assert(found_apps.all?{ |a| a.keys.all?(Symbol)})
|
636
638
|
return found_apps
|
637
639
|
end
|
638
640
|
|
@@ -640,8 +642,8 @@ module Aspera
|
|
640
642
|
command = options.get_next_command(%i[list info version])
|
641
643
|
if %i[info version].include?(command)
|
642
644
|
connect_id = options.get_next_argument('id or title')
|
643
|
-
one_res = Products::Connect.instance.versions.find{|i|i['id'].eql?(connect_id) || i['title'].eql?(connect_id)}
|
644
|
-
raise Cli::
|
645
|
+
one_res = Products::Connect.instance.versions.find{ |i| i['id'].eql?(connect_id) || i['title'].eql?(connect_id)}
|
646
|
+
raise Cli::BadIdentifier.new(:connect, connect_id) if one_res.nil?
|
645
647
|
end
|
646
648
|
case command
|
647
649
|
when :list
|
@@ -654,7 +656,7 @@ module Aspera
|
|
654
656
|
command = options.get_next_command(%i[list download open])
|
655
657
|
if %i[download open].include?(command)
|
656
658
|
link_title = options.get_next_argument('title or rel')
|
657
|
-
one_link = all_links.find
|
659
|
+
one_link = all_links.find{ |i| i['title'].eql?(link_title) || i['rel'].eql?(link_title)}
|
658
660
|
raise "no such value: #{link_title}" if one_link.nil?
|
659
661
|
end
|
660
662
|
case command
|
@@ -673,7 +675,7 @@ module Aspera
|
|
673
675
|
end
|
674
676
|
|
675
677
|
def execute_action_ascp
|
676
|
-
command = options.get_next_command(%i[connect use show products info install spec errors])
|
678
|
+
command = options.get_next_command(%i[connect use show products info install spec schema errors])
|
677
679
|
case command
|
678
680
|
when :connect
|
679
681
|
return execute_connect_action
|
@@ -691,7 +693,7 @@ module Aspera
|
|
691
693
|
# add command line transfer spec
|
692
694
|
data['ts'] = transfer.updated_ts
|
693
695
|
# add keys
|
694
|
-
DataRepository::ELEMENTS.each_with_object(data){|i, h|h[i.to_s] = DataRepository.instance.item(i)}
|
696
|
+
DataRepository::ELEMENTS.each_with_object(data){ |i, h| h[i.to_s] = DataRepository.instance.item(i)}
|
695
697
|
# declare those as secrets
|
696
698
|
SecretHider::ADDITIONAL_KEYS_TO_HIDE.concat(DataRepository::ELEMENTS.map(&:to_s))
|
697
699
|
return Main.result_single_object(data)
|
@@ -714,9 +716,15 @@ module Aspera
|
|
714
716
|
return Main.result_status("Installed #{n} version #{v}")
|
715
717
|
when :spec
|
716
718
|
return Main.result_object_list(
|
717
|
-
Transfer::
|
718
|
-
fields:
|
719
|
+
Transfer::SpecDoc.man_table(formatter, cli: false),
|
720
|
+
fields: Transfer::SpecDoc::TABLE_COLUMNS.map(&:to_s)
|
719
721
|
)
|
722
|
+
when :schema
|
723
|
+
schema = Transfer::Spec::SCHEMA.merge({'$comment'=>'DO NOT EDIT, this file was generated from the YAML.'})
|
724
|
+
agent = options.get_next_argument('transfer agent name', mandatory: false)
|
725
|
+
schema['properties'] = schema['properties'].select{ |_k, v| CommandLineBuilder.supported_by_agent(agent, v)} unless agent.nil?
|
726
|
+
schema['properties'] = schema['properties'].sort.to_h
|
727
|
+
return Main.result_single_object(schema)
|
720
728
|
when :errors
|
721
729
|
error_data = []
|
722
730
|
Transfer::ERROR_INFO.each_pair do |code, prop|
|
@@ -754,7 +762,7 @@ module Aspera
|
|
754
762
|
PRESET_EXIST_ACTIONS = %i[show delete get unset].freeze
|
755
763
|
# require id
|
756
764
|
PRESET_INSTANCE_ACTIONS = %i[initialize update ask set].concat(PRESET_EXIST_ACTIONS).freeze
|
757
|
-
PRESET_ALL_ACTIONS =
|
765
|
+
PRESET_ALL_ACTIONS = (PRESET_GBL_ACTIONS + PRESET_INSTANCE_ACTIONS).freeze
|
758
766
|
|
759
767
|
def execute_preset(action: nil, name: nil)
|
760
768
|
action = options.get_next_command(PRESET_ALL_ACTIONS) if action.nil?
|
@@ -786,7 +794,7 @@ module Aspera
|
|
786
794
|
value = @config_presets[name][param_name]
|
787
795
|
raise "no such option in preset #{name} : #{param_name}" if value.nil?
|
788
796
|
case value
|
789
|
-
when Numeric, String then return
|
797
|
+
when Numeric, String then return Main.result_text(ExtendedValue.instance.evaluate(value.to_s))
|
790
798
|
end
|
791
799
|
return Main.result_single_object(value)
|
792
800
|
when :unset
|
@@ -919,10 +927,10 @@ module Aspera
|
|
919
927
|
when :only
|
920
928
|
return Main.result_status(remote_chain.first.to_pem)
|
921
929
|
when :name
|
922
|
-
return Main.result_status(remote_chain.first.subject.to_a.find
|
930
|
+
return Main.result_status(remote_chain.first.subject.to_a.find{ |name, _, _| name == 'CN'}[1])
|
923
931
|
end
|
924
932
|
when :echo # display the content of a value given on command line
|
925
|
-
return
|
933
|
+
return Main.result_auto(options.get_next_argument('value', validation: nil))
|
926
934
|
when :download
|
927
935
|
file_url = options.get_next_argument('source URL').chomp
|
928
936
|
file_dest = options.get_next_argument('file path', mandatory: false)
|
@@ -1051,9 +1059,10 @@ module Aspera
|
|
1051
1059
|
else
|
1052
1060
|
formatter.display_status('Multiple applications detected, please select from:')
|
1053
1061
|
formatter.display_results(type: :object_list, data: apps, fields: %w[product url version])
|
1054
|
-
answer = options.prompt_user_input_in_list('product', apps.map{|a|a[:product]})
|
1055
|
-
apps.find{|a|a[:product].eql?(answer)}
|
1062
|
+
answer = options.prompt_user_input_in_list('product', apps.map{ |a| a[:product]})
|
1063
|
+
apps.find{ |a| a[:product].eql?(answer)}
|
1056
1064
|
end
|
1065
|
+
wiz_preset_name = options.get_next_argument('preset name', default: '')
|
1057
1066
|
Log.log.debug{Log.dump(:identification, identification)}
|
1058
1067
|
wiz_url = identification[:url]
|
1059
1068
|
formatter.display_status("Using: #{identification[:name]} at #{wiz_url}".bold)
|
@@ -1078,7 +1087,6 @@ module Aspera
|
|
1078
1087
|
if private_key_path.nil?
|
1079
1088
|
formatter.display_status('Please provide the path to your private RSA key, or nothing to generate one:')
|
1080
1089
|
private_key_path = options.get_option(:key_path, mandatory: true).to_s
|
1081
|
-
# private_key_path = File.expand_path(private_key_path)
|
1082
1090
|
end
|
1083
1091
|
# else generate path
|
1084
1092
|
if private_key_path.empty?
|
@@ -1103,13 +1111,12 @@ module Aspera
|
|
1103
1111
|
Log.log.debug{"wizard result: #{wizard_result}"}
|
1104
1112
|
Aspera.assert(WIZARD_RESULT_KEYS.eql?(wizard_result.keys.sort)){"missing or extra keys in wizard result: #{wizard_result.keys}"}
|
1105
1113
|
# get preset name from user or default
|
1106
|
-
wiz_preset_name
|
1107
|
-
if wiz_preset_name.nil?
|
1114
|
+
if wiz_preset_name.empty?
|
1108
1115
|
elements = [
|
1109
1116
|
identification[:product],
|
1110
1117
|
URI.parse(wiz_url).host
|
1111
1118
|
]
|
1112
|
-
elements.push(options.get_option(:username, mandatory: true)) unless wizard_result[:preset_value].key?(:link)
|
1119
|
+
elements.push(options.get_option(:username, mandatory: true)) unless wizard_result[:preset_value].key?(:link) rescue nil
|
1113
1120
|
wiz_preset_name = elements.join('_').strip.downcase.gsub(/[^a-z0-9]/, '_').squeeze('_')
|
1114
1121
|
end
|
1115
1122
|
# test mode does not change conf file
|
@@ -1138,9 +1145,12 @@ module Aspera
|
|
1138
1145
|
# @return [Hash] email server setting with defaults if not defined
|
1139
1146
|
def email_settings
|
1140
1147
|
smtp = options.get_option(:smtp, mandatory: true)
|
1141
|
-
# change string
|
1148
|
+
# change keys from string into symbol
|
1142
1149
|
smtp = smtp.symbolize_keys
|
1150
|
+
unsupported = smtp.keys - SMTP_CONF_PARAMS
|
1151
|
+
raise Cli::Error, "Unsupported SMTP parameter: #{unsupported.join(', ')}, use: #{SMTP_CONF_PARAMS.join(', ')}" unless unsupported.empty?
|
1143
1152
|
# defaults
|
1153
|
+
# smtp[:ssl] = nil (false)
|
1144
1154
|
smtp[:tls] = !smtp[:ssl] unless smtp.key?(:tls)
|
1145
1155
|
smtp[:port] ||= if smtp[:tls]
|
1146
1156
|
587
|
@@ -1169,8 +1179,8 @@ module Aspera
|
|
1169
1179
|
mail_conf = email_settings
|
1170
1180
|
values[:from_name] ||= mail_conf[:from_name]
|
1171
1181
|
values[:from_email] ||= mail_conf[:from_email]
|
1172
|
-
%i[
|
1173
|
-
Aspera.
|
1182
|
+
%i[to from_email].each do |n|
|
1183
|
+
Aspera.assert_type(values[n], String){"Missing email parameter: #{n} in config"}
|
1174
1184
|
end
|
1175
1185
|
start_options = [mail_conf[:domain]]
|
1176
1186
|
start_options.push(mail_conf[:username], mail_conf[:password], :login) if mail_conf.key?(:username) && mail_conf.key?(:password)
|
@@ -1204,7 +1214,7 @@ module Aspera
|
|
1204
1214
|
Environment.restrict_file_access(@main_folder)
|
1205
1215
|
Log.log.info{"Writing #{@option_config_file}"}
|
1206
1216
|
formatter.display_status('Saving config file.')
|
1207
|
-
Environment.write_file_restricted(@option_config_file, force: true)
|
1217
|
+
Environment.write_file_restricted(@option_config_file, force: true){@config_presets.to_yaml}
|
1208
1218
|
@config_checksum_on_disk = current_checksum
|
1209
1219
|
return true
|
1210
1220
|
end
|
@@ -1234,15 +1244,15 @@ module Aspera
|
|
1234
1244
|
return nil
|
1235
1245
|
end
|
1236
1246
|
|
1237
|
-
# TODO: delete: ALLOWED_KEYS = %i[password username description].freeze
|
1238
1247
|
# @return [Hash] result of execution of vault command
|
1239
1248
|
def execute_vault
|
1240
1249
|
command = options.get_next_command(%i[info list show create delete password])
|
1241
1250
|
case command
|
1242
1251
|
when :info
|
1243
|
-
return Main.result_single_object(
|
1252
|
+
return Main.result_single_object(vault.info)
|
1244
1253
|
when :list
|
1245
|
-
|
1254
|
+
# , fields: %w(label url username password description)
|
1255
|
+
return Main.result_object_list(vault.list)
|
1246
1256
|
when :show
|
1247
1257
|
return Main.result_single_object(vault.get(label: options.get_next_argument('label')))
|
1248
1258
|
when :create
|
@@ -1251,17 +1261,15 @@ module Aspera
|
|
1251
1261
|
info = info.symbolize_keys
|
1252
1262
|
info[:label] = label
|
1253
1263
|
vault.set(info)
|
1254
|
-
return Main.result_status('
|
1264
|
+
return Main.result_status('Secret added')
|
1255
1265
|
when :delete
|
1256
1266
|
label_to_delete = options.get_next_argument('label')
|
1257
1267
|
vault.delete(label: label_to_delete)
|
1258
|
-
return Main.result_status("
|
1268
|
+
return Main.result_status("Secret deleted: #{label_to_delete}")
|
1259
1269
|
when :password
|
1260
|
-
Aspera.assert(vault.respond_to?(:
|
1261
|
-
|
1262
|
-
|
1263
|
-
vault.save
|
1264
|
-
return Main.result_status('Password updated')
|
1270
|
+
Aspera.assert(vault.respond_to?(:change_password)){'Vault does not support password change'}
|
1271
|
+
vault.change_password(options.get_next_argument('new_password'))
|
1272
|
+
return Main.result_status('Vault password updated')
|
1265
1273
|
end
|
1266
1274
|
end
|
1267
1275
|
|
@@ -1276,42 +1284,18 @@ module Aspera
|
|
1276
1284
|
return value
|
1277
1285
|
end
|
1278
1286
|
|
1279
|
-
def vault_info
|
1280
|
-
info = options.get_option(:vault) || {}
|
1281
|
-
info = info.symbolize_keys
|
1282
|
-
info[:type] ||= 'file'
|
1283
|
-
info[:name] ||= (info[:type].eql?('file') ? DEFAULT_VAULT_FILENAME : Info::CMD_NAME)
|
1284
|
-
Aspera.assert(info.keys.sort == %i[name type]) {"vault info shall have exactly keys 'type' and 'name'"}
|
1285
|
-
Aspera.assert(info.values.all?(String)){'vault info shall have only string values'}
|
1286
|
-
info[:password] = options.get_option(:vault_password, mandatory: true)
|
1287
|
-
return info
|
1288
|
-
end
|
1289
|
-
|
1290
1287
|
# @return [Object] vault, from options or cache
|
1291
1288
|
def vault
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
when 'system'
|
1303
|
-
case Environment.os
|
1304
|
-
when Environment::OS_MACOS
|
1305
|
-
@vault = Keychain::MacosSystem.new(info[:name], info[:password])
|
1306
|
-
else
|
1307
|
-
raise 'not implemented for this OS'
|
1308
|
-
end
|
1309
|
-
else
|
1310
|
-
raise Cli::BadArgument, "Unknown vault type: #{info[:type]}"
|
1311
|
-
end
|
1312
|
-
end
|
1313
|
-
raise 'No vault defined' if @vault.nil?
|
1314
|
-
@vault
|
1289
|
+
return @vault_instance unless @vault_instance.nil?
|
1290
|
+
info = options.get_option(:vault).symbolize_keys
|
1291
|
+
info[:type] ||= 'file'
|
1292
|
+
require 'aspera/keychain/factory'
|
1293
|
+
@vault_instance = Keychain::Factory.create(
|
1294
|
+
info,
|
1295
|
+
Info::CMD_NAME,
|
1296
|
+
@main_folder,
|
1297
|
+
options.get_option(:vault_password)
|
1298
|
+
)
|
1315
1299
|
end
|
1316
1300
|
|
1317
1301
|
def execute_test
|
@@ -40,7 +40,9 @@ module Aspera
|
|
40
40
|
return nil
|
41
41
|
end
|
42
42
|
|
43
|
-
|
43
|
+
# @param object [Plugin] An instance of this class
|
44
|
+
# @return [Hash] :preset_value, :test_args
|
45
|
+
def wizard(object:)
|
44
46
|
options = object.options
|
45
47
|
return {
|
46
48
|
preset_value: {
|
@@ -84,11 +86,11 @@ module Aspera
|
|
84
86
|
command = options.get_next_command(%i[list submit])
|
85
87
|
case command
|
86
88
|
when :list
|
87
|
-
return
|
89
|
+
return Main.result_object_list(api_console.read('smart_transfers'))
|
88
90
|
when :submit
|
89
91
|
smart_id = options.get_next_argument('smart_id')
|
90
92
|
params = options.get_next_argument('transfer parameters')
|
91
|
-
return
|
93
|
+
return Main.result_object_list(api_console.create("smart_transfers/#{smart_id}", params))
|
92
94
|
end
|
93
95
|
when :current
|
94
96
|
command = options.get_next_command([:list])
|