aspera-cli 4.21.1 → 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 +52 -22
- data/CONTRIBUTING.md +69 -148
- data/README.md +929 -668
- data/bin/ascli +5 -14
- data/bin/asession +1 -3
- data/examples/get_proto_file.rb +4 -3
- data/examples/proxy.pac +20 -20
- data/lib/aspera/agent/base.rb +11 -5
- data/lib/aspera/agent/connect.rb +30 -28
- data/lib/aspera/agent/{alpha.rb → desktop.rb} +35 -31
- data/lib/aspera/agent/direct.rb +141 -121
- data/lib/aspera/agent/httpgw.rb +22 -26
- data/lib/aspera/agent/node.rb +14 -11
- data/lib/aspera/agent/transferd.rb +30 -19
- data/lib/aspera/api/alee.rb +1 -1
- data/lib/aspera/api/aoc.rb +6 -6
- data/lib/aspera/api/cos_node.rb +2 -2
- data/lib/aspera/api/httpgw.rb +7 -3
- data/lib/aspera/api/node.rb +10 -8
- data/lib/aspera/ascmd.rb +3 -3
- data/lib/aspera/ascp/installation.rb +53 -72
- 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 +46 -21
- data/lib/aspera/cli/formatter.rb +55 -48
- data/lib/aspera/cli/hints.rb +1 -1
- data/lib/aspera/cli/info.rb +1 -0
- data/lib/aspera/cli/main.rb +192 -170
- data/lib/aspera/cli/manager.rb +18 -18
- 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 +247 -159
- data/lib/aspera/cli/plugins/ats.rb +19 -17
- data/lib/aspera/cli/plugins/config.rb +76 -113
- 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 +111 -84
- 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 +312 -182
- 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 +8 -5
- data/lib/aspera/environment.rb +26 -17
- data/lib/aspera/faspex_gw.rb +14 -14
- data/lib/aspera/faspex_postproc.rb +10 -11
- data/lib/aspera/hash_ext.rb +4 -14
- 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 +14 -7
- 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 +13 -10
- data/lib/aspera/preview/options.rb +16 -16
- data/lib/aspera/preview/terminal.rb +4 -4
- data/lib/aspera/preview/utils.rb +15 -17
- data/lib/aspera/products/connect.rb +35 -1
- data/lib/aspera/products/{alpha.rb → desktop.rb} +3 -3
- data/lib/aspera/products/transferd.rb +9 -2
- data/lib/aspera/proxy_auto_config.rb +2 -2
- data/lib/aspera/rest.rb +56 -47
- data/lib/aspera/rest_errors_aspera.rb +1 -1
- data/lib/aspera/secret_hider.rb +12 -5
- data/lib/aspera/ssh.rb +4 -4
- data/lib/aspera/temp_file_manager.rb +5 -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 +18 -1
- data/lib/aspera/web_auth.rb +1 -1
- data/lib/aspera/web_server_simple.rb +53 -44
- data.tar.gz.sig +0 -0
- metadata +28 -165
- metadata.gz.sig +0 -0
- data/examples/build_exec +0 -74
- data/examples/build_exec_rubyc +0 -40
- 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'
|
@@ -54,8 +54,6 @@ module Aspera
|
|
54
54
|
ASPERA = 'aspera'
|
55
55
|
SERVER_COMMAND = 'server'
|
56
56
|
DIR_SDK = 'sdk'
|
57
|
-
CONNECT_WEB_URL = 'https://d3gcli72yxqn2z.cloudfront.net/connect'
|
58
|
-
CONNECT_VERSIONS = 'connectversions.js' # cspell: disable-line
|
59
57
|
DEMO_SERVER = 'demo'
|
60
58
|
DEMO_PRESET = 'demoserver' # cspell: disable-line
|
61
59
|
EMAIL_TEST_TEMPLATE = <<~END_OF_TEMPLATE
|
@@ -78,6 +76,7 @@ module Aspera
|
|
78
76
|
# for testing only
|
79
77
|
SELF_SIGNED_CERT = OpenSSL::SSL.const_get(:enon_yfirev.to_s.upcase.reverse) # cspell: disable-line
|
80
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
|
81
80
|
private_constant :DEFAULT_CONFIG_FILENAME,
|
82
81
|
:CONF_PRESET_CONFIG,
|
83
82
|
:CONF_PRESET_VERSION,
|
@@ -99,7 +98,8 @@ module Aspera
|
|
99
98
|
:SELF_SIGNED_CERT,
|
100
99
|
:PERSISTENCY_FOLDER,
|
101
100
|
:DEFAULT_PRIV_KEY_LENGTH,
|
102
|
-
:CONF_OVERVIEW_KEYS
|
101
|
+
:CONF_OVERVIEW_KEYS,
|
102
|
+
:SMTP_CONF_PARAMS
|
103
103
|
|
104
104
|
class << self
|
105
105
|
def generate_rsa_private_key(path:, length: DEFAULT_PRIV_KEY_LENGTH)
|
@@ -144,14 +144,13 @@ module Aspera
|
|
144
144
|
end
|
145
145
|
end
|
146
146
|
|
147
|
-
def initialize(**
|
147
|
+
def initialize(**_)
|
148
148
|
# we need to defer parsing of options until we have the config file, so we can use @extend with @preset
|
149
149
|
super
|
150
150
|
@use_plugin_defaults = true
|
151
151
|
@config_presets = nil
|
152
152
|
@config_checksum_on_disk = nil
|
153
|
-
@
|
154
|
-
@vault = nil
|
153
|
+
@vault_instance = nil
|
155
154
|
@pac_exec = nil
|
156
155
|
@sdk_default_location = false
|
157
156
|
@option_insecure = false
|
@@ -175,8 +174,8 @@ module Aspera
|
|
175
174
|
default: self.class.default_app_main_folder(app_name: Info::CMD_NAME))
|
176
175
|
options.parse_options!
|
177
176
|
Log.log.debug{"#{Info::CMD_NAME} folder: #{@main_folder}"}
|
178
|
-
# data persistency manager, created by config plugin
|
179
|
-
@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))
|
180
179
|
# set folders for plugin lookup
|
181
180
|
PluginFactory.instance.add_lookup_folder(self.class.gem_plugins_folder)
|
182
181
|
PluginFactory.instance.add_lookup_folder(File.join(@main_folder, ASPERA_PLUGINS_FOLDERNAME))
|
@@ -189,19 +188,19 @@ module Aspera
|
|
189
188
|
# read config file (set @config_presets)
|
190
189
|
read_config_file
|
191
190
|
# add preset handler (needed for smtp)
|
192
|
-
ExtendedValue.instance.set_handler(EXTEND_PRESET, lambda{|v|preset_by_name(v)})
|
193
|
-
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)})
|
194
193
|
# load defaults before it can be overridden
|
195
194
|
add_plugin_default_preset(CONF_GLOBAL_SYM)
|
196
195
|
# vault options
|
197
196
|
options.declare(:secret, 'Secret for access keys')
|
198
|
-
options.declare(:vault, 'Vault for secrets', types: Hash)
|
197
|
+
options.declare(:vault, 'Vault for secrets', types: Hash, default: {})
|
199
198
|
options.declare(:vault_password, 'Vault password')
|
200
199
|
options.parse_options!
|
201
200
|
# declare generic plugin options only after handlers are declared
|
202
201
|
Plugin.declare_generic_options(options)
|
203
202
|
# configuration options
|
204
|
-
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}
|
205
204
|
options.declare(:preset, 'Load the named option preset from current config file', short: 'P', handler: {o: self, m: :option_preset})
|
206
205
|
options.declare(:version_check_days, 'Period in days to check new version (zero to disable)', coerce: Integer, default: DEFAULT_CHECK_NEW_VERSION_DAYS)
|
207
206
|
options.declare(:plugin_folder, 'Folder where to find additional plugins', handler: {o: self, m: :option_plugin_folder})
|
@@ -213,7 +212,8 @@ module Aspera
|
|
213
212
|
# Transfer SDK options
|
214
213
|
options.declare(:ascp_path, 'Path to ascp', handler: {o: Ascp::Installation.instance, m: :ascp_path})
|
215
214
|
options.declare(:use_product, 'Use ascp from specified product', handler: {o: self, m: :option_use_product})
|
216
|
-
options.declare(:sdk_url, 'URL to get
|
215
|
+
options.declare(:sdk_url, 'URL to get Aspera Transfer Daemon', default: SpecialValues::DEF)
|
216
|
+
options.declare(:locations_url, 'URL to get locations of Aspera Transfer Daemon', handler: {o: Ascp::Installation.instance, m: :transferd_urls})
|
217
217
|
options.declare(:sdk_folder, 'SDK folder path', handler: {o: Products::Transferd, m: :sdk_directory})
|
218
218
|
options.declare(:progress_bar, 'Display progress bar', values: :bool, default: Environment.terminal?)
|
219
219
|
# email options
|
@@ -263,8 +263,8 @@ module Aspera
|
|
263
263
|
end
|
264
264
|
RestParameters.instance.user_agent = Info::CMD_NAME
|
265
265
|
RestParameters.instance.progress_bar = @progress_bar
|
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
|
+
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|
|
268
268
|
method = "#{k}=".to_sym
|
269
269
|
RestParameters.instance.send(method, @option_http_options[k])
|
270
270
|
@option_http_options.delete(k)
|
@@ -301,7 +301,7 @@ module Aspera
|
|
301
301
|
paths_to_add = [OpenSSL::X509::DEFAULT_CERT_DIR]
|
302
302
|
# JRuby cert file seems not to be PEM
|
303
303
|
paths_to_add.push(OpenSSL::X509::DEFAULT_CERT_FILE) unless defined?(JRUBY_VERSION)
|
304
|
-
paths_to_add.select!{|f|File.exist?(f)}
|
304
|
+
paths_to_add.select!{ |f| File.exist?(f)}
|
305
305
|
elsif File.file?(path)
|
306
306
|
@certificate_store.add_file(path)
|
307
307
|
elsif File.directory?(path)
|
@@ -313,8 +313,8 @@ module Aspera
|
|
313
313
|
pp = [File.realpath(p)]
|
314
314
|
if File.directory?(p)
|
315
315
|
pp = Dir.entries(p)
|
316
|
-
.map{|e|File.realpath(File.join(p, e))}
|
317
|
-
.select{|entry|File.file?(entry)}
|
316
|
+
.map{ |e| File.realpath(File.join(p, e))}
|
317
|
+
.select{ |entry| File.file?(entry)}
|
318
318
|
end
|
319
319
|
@certificate_paths.concat(pp)
|
320
320
|
end
|
@@ -439,23 +439,6 @@ module Aspera
|
|
439
439
|
end if check_data[:need_update]
|
440
440
|
end
|
441
441
|
|
442
|
-
# retrieve structure from cloud (CDN) with all versions available
|
443
|
-
def connect_versions
|
444
|
-
if @connect_versions.nil?
|
445
|
-
api_connect_cdn = Rest.new(base_url: CONNECT_WEB_URL)
|
446
|
-
javascript = api_connect_cdn.call(operation: 'GET', subpath: CONNECT_VERSIONS)
|
447
|
-
# get result on one line
|
448
|
-
connect_versions_javascript = javascript[:http].body.gsub(/\r?\n\s*/, '')
|
449
|
-
Log.log.debug{"javascript=[\n#{connect_versions_javascript}\n]"}
|
450
|
-
# get javascript object only
|
451
|
-
found = connect_versions_javascript.match(/^.*? = (.*);/)
|
452
|
-
raise Cli::Error, 'Problem when getting connect versions from internet' if found.nil?
|
453
|
-
all_data = JSON.parse(found[1])
|
454
|
-
@connect_versions = all_data['entries']
|
455
|
-
end
|
456
|
-
return @connect_versions
|
457
|
-
end
|
458
|
-
|
459
442
|
# loads default parameters of plugin if no -P parameter
|
460
443
|
# and if there is a section defined for the plugin in the "default" section
|
461
444
|
# try to find: conf[conf["default"][plugin_str]]
|
@@ -538,7 +521,7 @@ module Aspera
|
|
538
521
|
Aspera.assert_values(value.class, [String, Array]){'plugin folder'}
|
539
522
|
value = [value] if value.is_a?(String)
|
540
523
|
Aspera.assert(value.all?(String)){'plugin folder'}
|
541
|
-
value.each{|f|PluginFactory.instance.add_lookup_folder(f)}
|
524
|
+
value.each{ |f| PluginFactory.instance.add_lookup_folder(f)}
|
542
525
|
end
|
543
526
|
|
544
527
|
def option_plugin_folder
|
@@ -568,7 +551,7 @@ module Aspera
|
|
568
551
|
# files search for configuration, by default the one given by user
|
569
552
|
search_files = [@option_config_file]
|
570
553
|
# find first existing file (or nil)
|
571
|
-
conf_file_to_load = search_files.find{|f| File.exist?(f)}
|
554
|
+
conf_file_to_load = search_files.find{ |f| File.exist?(f)}
|
572
555
|
# if no file found, create default config
|
573
556
|
if conf_file_to_load.nil?
|
574
557
|
Log.log.warn{"No config file found. New configuration file: #{@option_config_file}"}
|
@@ -651,7 +634,7 @@ module Aspera
|
|
651
634
|
found_apps.push({product: plugin_name_sym, name: app_name, url: app_url, version: 'unknown'}.merge(detection_info))
|
652
635
|
end
|
653
636
|
raise "No known application found at #{app_url}" if found_apps.empty?
|
654
|
-
Aspera.assert(found_apps.all?{|a|a.keys.all?(Symbol)})
|
637
|
+
Aspera.assert(found_apps.all?{ |a| a.keys.all?(Symbol)})
|
655
638
|
return found_apps
|
656
639
|
end
|
657
640
|
|
@@ -659,12 +642,12 @@ module Aspera
|
|
659
642
|
command = options.get_next_command(%i[list info version])
|
660
643
|
if %i[info version].include?(command)
|
661
644
|
connect_id = options.get_next_argument('id or title')
|
662
|
-
one_res =
|
663
|
-
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?
|
664
647
|
end
|
665
648
|
case command
|
666
649
|
when :list
|
667
|
-
return Main.result_object_list(
|
650
|
+
return Main.result_object_list(Products::Connect.instance.versions, fields: %w[id title version])
|
668
651
|
when :info
|
669
652
|
one_res.delete('links')
|
670
653
|
return Main.result_single_object(one_res)
|
@@ -673,19 +656,17 @@ module Aspera
|
|
673
656
|
command = options.get_next_command(%i[list download open])
|
674
657
|
if %i[download open].include?(command)
|
675
658
|
link_title = options.get_next_argument('title or rel')
|
676
|
-
one_link = all_links.find
|
677
|
-
raise
|
659
|
+
one_link = all_links.find{ |i| i['title'].eql?(link_title) || i['rel'].eql?(link_title)}
|
660
|
+
raise "no such value: #{link_title}" if one_link.nil?
|
678
661
|
end
|
679
662
|
case command
|
680
663
|
when :list
|
681
664
|
return Main.result_object_list(all_links)
|
682
665
|
when :download
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
api_connect_cdn.call(operation: 'GET', subpath: file_url, save_to_file: File.join(folder_dest, filename))
|
688
|
-
return Main.result_status("Downloaded: #{filename}")
|
666
|
+
archive_path = one_link['href']
|
667
|
+
save_to_path = File.join(transfer.destination_folder(Transfer::Spec::DIRECTION_RECEIVE), archive_path.gsub(%r{.*/}, ''))
|
668
|
+
Products::Connect.instance.cdn_api.call(operation: 'GET', subpath: archive_path, save_to_file: save_to_path)
|
669
|
+
return Main.result_status("Downloaded: #{save_to_path}")
|
689
670
|
when :open
|
690
671
|
Environment.instance.open_uri(one_link['href'])
|
691
672
|
return Main.result_status("Opened: #{one_link['href']}")
|
@@ -694,7 +675,7 @@ module Aspera
|
|
694
675
|
end
|
695
676
|
|
696
677
|
def execute_action_ascp
|
697
|
-
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])
|
698
679
|
case command
|
699
680
|
when :connect
|
700
681
|
return execute_connect_action
|
@@ -712,7 +693,7 @@ module Aspera
|
|
712
693
|
# add command line transfer spec
|
713
694
|
data['ts'] = transfer.updated_ts
|
714
695
|
# add keys
|
715
|
-
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)}
|
716
697
|
# declare those as secrets
|
717
698
|
SecretHider::ADDITIONAL_KEYS_TO_HIDE.concat(DataRepository::ELEMENTS.map(&:to_s))
|
718
699
|
return Main.result_single_object(data)
|
@@ -735,9 +716,15 @@ module Aspera
|
|
735
716
|
return Main.result_status("Installed #{n} version #{v}")
|
736
717
|
when :spec
|
737
718
|
return Main.result_object_list(
|
738
|
-
Transfer::
|
739
|
-
fields:
|
719
|
+
Transfer::SpecDoc.man_table(formatter, cli: false),
|
720
|
+
fields: Transfer::SpecDoc::TABLE_COLUMNS.map(&:to_s)
|
740
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)
|
741
728
|
when :errors
|
742
729
|
error_data = []
|
743
730
|
Transfer::ERROR_INFO.each_pair do |code, prop|
|
@@ -759,7 +746,7 @@ module Aspera
|
|
759
746
|
n, v = Ascp::Installation.instance.install_sdk(url: options.get_option(:sdk_url, mandatory: true), version: version)
|
760
747
|
return Main.result_status("Installed #{n} version #{v}")
|
761
748
|
when :list
|
762
|
-
sdk_list = Ascp::Installation.sdk_locations
|
749
|
+
sdk_list = Ascp::Installation.instance.sdk_locations
|
763
750
|
return Main.result_object_list(
|
764
751
|
sdk_list,
|
765
752
|
fields: sdk_list.first.keys - ['url']
|
@@ -775,7 +762,7 @@ module Aspera
|
|
775
762
|
PRESET_EXIST_ACTIONS = %i[show delete get unset].freeze
|
776
763
|
# require id
|
777
764
|
PRESET_INSTANCE_ACTIONS = %i[initialize update ask set].concat(PRESET_EXIST_ACTIONS).freeze
|
778
|
-
PRESET_ALL_ACTIONS =
|
765
|
+
PRESET_ALL_ACTIONS = (PRESET_GBL_ACTIONS + PRESET_INSTANCE_ACTIONS).freeze
|
779
766
|
|
780
767
|
def execute_preset(action: nil, name: nil)
|
781
768
|
action = options.get_next_command(PRESET_ALL_ACTIONS) if action.nil?
|
@@ -807,7 +794,7 @@ module Aspera
|
|
807
794
|
value = @config_presets[name][param_name]
|
808
795
|
raise "no such option in preset #{name} : #{param_name}" if value.nil?
|
809
796
|
case value
|
810
|
-
when Numeric, String then return
|
797
|
+
when Numeric, String then return Main.result_text(ExtendedValue.instance.evaluate(value.to_s))
|
811
798
|
end
|
812
799
|
return Main.result_single_object(value)
|
813
800
|
when :unset
|
@@ -940,10 +927,10 @@ module Aspera
|
|
940
927
|
when :only
|
941
928
|
return Main.result_status(remote_chain.first.to_pem)
|
942
929
|
when :name
|
943
|
-
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])
|
944
931
|
end
|
945
932
|
when :echo # display the content of a value given on command line
|
946
|
-
return
|
933
|
+
return Main.result_auto(options.get_next_argument('value', validation: nil))
|
947
934
|
when :download
|
948
935
|
file_url = options.get_next_argument('source URL').chomp
|
949
936
|
file_dest = options.get_next_argument('file path', mandatory: false)
|
@@ -1072,9 +1059,10 @@ module Aspera
|
|
1072
1059
|
else
|
1073
1060
|
formatter.display_status('Multiple applications detected, please select from:')
|
1074
1061
|
formatter.display_results(type: :object_list, data: apps, fields: %w[product url version])
|
1075
|
-
answer = options.prompt_user_input_in_list('product', apps.map{|a|a[:product]})
|
1076
|
-
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)}
|
1077
1064
|
end
|
1065
|
+
wiz_preset_name = options.get_next_argument('preset name', default: '')
|
1078
1066
|
Log.log.debug{Log.dump(:identification, identification)}
|
1079
1067
|
wiz_url = identification[:url]
|
1080
1068
|
formatter.display_status("Using: #{identification[:name]} at #{wiz_url}".bold)
|
@@ -1099,7 +1087,6 @@ module Aspera
|
|
1099
1087
|
if private_key_path.nil?
|
1100
1088
|
formatter.display_status('Please provide the path to your private RSA key, or nothing to generate one:')
|
1101
1089
|
private_key_path = options.get_option(:key_path, mandatory: true).to_s
|
1102
|
-
# private_key_path = File.expand_path(private_key_path)
|
1103
1090
|
end
|
1104
1091
|
# else generate path
|
1105
1092
|
if private_key_path.empty?
|
@@ -1124,13 +1111,12 @@ module Aspera
|
|
1124
1111
|
Log.log.debug{"wizard result: #{wizard_result}"}
|
1125
1112
|
Aspera.assert(WIZARD_RESULT_KEYS.eql?(wizard_result.keys.sort)){"missing or extra keys in wizard result: #{wizard_result.keys}"}
|
1126
1113
|
# get preset name from user or default
|
1127
|
-
wiz_preset_name
|
1128
|
-
if wiz_preset_name.nil?
|
1114
|
+
if wiz_preset_name.empty?
|
1129
1115
|
elements = [
|
1130
1116
|
identification[:product],
|
1131
1117
|
URI.parse(wiz_url).host
|
1132
1118
|
]
|
1133
|
-
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
|
1134
1120
|
wiz_preset_name = elements.join('_').strip.downcase.gsub(/[^a-z0-9]/, '_').squeeze('_')
|
1135
1121
|
end
|
1136
1122
|
# test mode does not change conf file
|
@@ -1159,9 +1145,12 @@ module Aspera
|
|
1159
1145
|
# @return [Hash] email server setting with defaults if not defined
|
1160
1146
|
def email_settings
|
1161
1147
|
smtp = options.get_option(:smtp, mandatory: true)
|
1162
|
-
# change string
|
1148
|
+
# change keys from string into symbol
|
1163
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?
|
1164
1152
|
# defaults
|
1153
|
+
# smtp[:ssl] = nil (false)
|
1165
1154
|
smtp[:tls] = !smtp[:ssl] unless smtp.key?(:tls)
|
1166
1155
|
smtp[:port] ||= if smtp[:tls]
|
1167
1156
|
587
|
@@ -1190,8 +1179,8 @@ module Aspera
|
|
1190
1179
|
mail_conf = email_settings
|
1191
1180
|
values[:from_name] ||= mail_conf[:from_name]
|
1192
1181
|
values[:from_email] ||= mail_conf[:from_email]
|
1193
|
-
%i[
|
1194
|
-
Aspera.
|
1182
|
+
%i[to from_email].each do |n|
|
1183
|
+
Aspera.assert_type(values[n], String){"Missing email parameter: #{n} in config"}
|
1195
1184
|
end
|
1196
1185
|
start_options = [mail_conf[:domain]]
|
1197
1186
|
start_options.push(mail_conf[:username], mail_conf[:password], :login) if mail_conf.key?(:username) && mail_conf.key?(:password)
|
@@ -1225,7 +1214,7 @@ module Aspera
|
|
1225
1214
|
Environment.restrict_file_access(@main_folder)
|
1226
1215
|
Log.log.info{"Writing #{@option_config_file}"}
|
1227
1216
|
formatter.display_status('Saving config file.')
|
1228
|
-
Environment.write_file_restricted(@option_config_file, force: true)
|
1217
|
+
Environment.write_file_restricted(@option_config_file, force: true){@config_presets.to_yaml}
|
1229
1218
|
@config_checksum_on_disk = current_checksum
|
1230
1219
|
return true
|
1231
1220
|
end
|
@@ -1255,15 +1244,15 @@ module Aspera
|
|
1255
1244
|
return nil
|
1256
1245
|
end
|
1257
1246
|
|
1258
|
-
# TODO: delete: ALLOWED_KEYS = %i[password username description].freeze
|
1259
1247
|
# @return [Hash] result of execution of vault command
|
1260
1248
|
def execute_vault
|
1261
1249
|
command = options.get_next_command(%i[info list show create delete password])
|
1262
1250
|
case command
|
1263
1251
|
when :info
|
1264
|
-
return Main.result_single_object(
|
1252
|
+
return Main.result_single_object(vault.info)
|
1265
1253
|
when :list
|
1266
|
-
|
1254
|
+
# , fields: %w(label url username password description)
|
1255
|
+
return Main.result_object_list(vault.list)
|
1267
1256
|
when :show
|
1268
1257
|
return Main.result_single_object(vault.get(label: options.get_next_argument('label')))
|
1269
1258
|
when :create
|
@@ -1272,17 +1261,15 @@ module Aspera
|
|
1272
1261
|
info = info.symbolize_keys
|
1273
1262
|
info[:label] = label
|
1274
1263
|
vault.set(info)
|
1275
|
-
return Main.result_status('
|
1264
|
+
return Main.result_status('Secret added')
|
1276
1265
|
when :delete
|
1277
1266
|
label_to_delete = options.get_next_argument('label')
|
1278
1267
|
vault.delete(label: label_to_delete)
|
1279
|
-
return Main.result_status("
|
1268
|
+
return Main.result_status("Secret deleted: #{label_to_delete}")
|
1280
1269
|
when :password
|
1281
|
-
Aspera.assert(vault.respond_to?(:
|
1282
|
-
|
1283
|
-
|
1284
|
-
vault.save
|
1285
|
-
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')
|
1286
1273
|
end
|
1287
1274
|
end
|
1288
1275
|
|
@@ -1297,42 +1284,18 @@ module Aspera
|
|
1297
1284
|
return value
|
1298
1285
|
end
|
1299
1286
|
|
1300
|
-
def vault_info
|
1301
|
-
info = options.get_option(:vault) || {}
|
1302
|
-
info = info.symbolize_keys
|
1303
|
-
info[:type] ||= 'file'
|
1304
|
-
info[:name] ||= (info[:type].eql?('file') ? DEFAULT_VAULT_FILENAME : Info::CMD_NAME)
|
1305
|
-
Aspera.assert(info.keys.sort == %i[name type]) {"vault info shall have exactly keys 'type' and 'name'"}
|
1306
|
-
Aspera.assert(info.values.all?(String)){'vault info shall have only string values'}
|
1307
|
-
info[:password] = options.get_option(:vault_password, mandatory: true)
|
1308
|
-
return info
|
1309
|
-
end
|
1310
|
-
|
1311
1287
|
# @return [Object] vault, from options or cache
|
1312
1288
|
def vault
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
when 'system'
|
1324
|
-
case Environment.os
|
1325
|
-
when Environment::OS_MACOS
|
1326
|
-
@vault = Keychain::MacosSystem.new(info[:name], info[:password])
|
1327
|
-
else
|
1328
|
-
raise 'not implemented for this OS'
|
1329
|
-
end
|
1330
|
-
else
|
1331
|
-
raise Cli::BadArgument, "Unknown vault type: #{info[:type]}"
|
1332
|
-
end
|
1333
|
-
end
|
1334
|
-
raise 'No vault defined' if @vault.nil?
|
1335
|
-
@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
|
+
)
|
1336
1299
|
end
|
1337
1300
|
|
1338
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])
|