aspera-cli 4.0.0 → 4.2.2
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
- data/README.md +843 -304
- data/bin/dascli +13 -0
- data/docs/Makefile +4 -4
- data/docs/README.erb.md +805 -172
- data/docs/test_env.conf +22 -3
- data/examples/aoc.rb +14 -3
- data/examples/faspex4.rb +89 -0
- data/lib/aspera/aoc.rb +87 -108
- data/lib/aspera/cli/formater.rb +2 -0
- data/lib/aspera/cli/main.rb +89 -49
- data/lib/aspera/cli/plugin.rb +9 -4
- data/lib/aspera/cli/plugins/alee.rb +1 -1
- data/lib/aspera/cli/plugins/aoc.rb +188 -173
- data/lib/aspera/cli/plugins/ats.rb +2 -2
- data/lib/aspera/cli/plugins/config.rb +218 -145
- data/lib/aspera/cli/plugins/console.rb +2 -2
- data/lib/aspera/cli/plugins/faspex.rb +114 -61
- data/lib/aspera/cli/plugins/faspex5.rb +85 -43
- data/lib/aspera/cli/plugins/node.rb +3 -3
- data/lib/aspera/cli/plugins/preview.rb +59 -45
- data/lib/aspera/cli/plugins/server.rb +23 -8
- data/lib/aspera/cli/transfer_agent.rb +77 -49
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/command_line_builder.rb +49 -31
- data/lib/aspera/cos_node.rb +33 -28
- data/lib/aspera/environment.rb +2 -2
- data/lib/aspera/fasp/connect.rb +28 -21
- data/lib/aspera/fasp/http_gw.rb +140 -28
- data/lib/aspera/fasp/installation.rb +93 -46
- data/lib/aspera/fasp/local.rb +88 -45
- data/lib/aspera/fasp/manager.rb +15 -0
- data/lib/aspera/fasp/node.rb +4 -4
- data/lib/aspera/fasp/parameters.rb +59 -101
- data/lib/aspera/fasp/parameters.yaml +531 -0
- data/lib/aspera/fasp/resume_policy.rb +13 -12
- data/lib/aspera/fasp/uri.rb +1 -1
- data/lib/aspera/log.rb +1 -1
- data/lib/aspera/node.rb +61 -1
- data/lib/aspera/oauth.rb +49 -46
- data/lib/aspera/persistency_folder.rb +9 -4
- data/lib/aspera/preview/file_types.rb +53 -21
- data/lib/aspera/preview/generator.rb +3 -3
- data/lib/aspera/rest.rb +29 -18
- data/lib/aspera/secrets.rb +20 -0
- data/lib/aspera/sync.rb +40 -35
- data/lib/aspera/temp_file_manager.rb +19 -0
- data/lib/aspera/web_auth.rb +105 -0
- metadata +54 -20
- data/docs/transfer_spec.html +0 -99
@@ -1,16 +1,20 @@
|
|
1
1
|
require 'aspera/cli/basic_auth_plugin'
|
2
2
|
require 'aspera/cli/extended_value'
|
3
3
|
require 'aspera/fasp/installation'
|
4
|
+
require 'aspera/fasp/parameters'
|
4
5
|
require 'aspera/api_detector'
|
5
6
|
require 'aspera/open_application'
|
6
7
|
require 'aspera/aoc'
|
7
8
|
require 'aspera/proxy_auto_config'
|
8
9
|
require 'aspera/uri_reader'
|
9
10
|
require 'aspera/rest'
|
11
|
+
require 'aspera/persistency_action_once'
|
10
12
|
require 'xmlsimple'
|
11
13
|
require 'base64'
|
12
14
|
require 'net/smtp'
|
13
15
|
require 'open3'
|
16
|
+
require 'date'
|
17
|
+
require 'erb'
|
14
18
|
|
15
19
|
module Aspera
|
16
20
|
module Cli
|
@@ -25,6 +29,7 @@ module Aspera
|
|
25
29
|
CONF_PRESET_CONFIG='config'
|
26
30
|
CONF_PRESET_VERSION='version'
|
27
31
|
CONF_PRESET_DEFAULT='default'
|
32
|
+
CONF_PRESET_GLOBAL='global_common_defaults'
|
28
33
|
CONF_PLUGIN_SYM = :config # Plugins::Config.name.split('::').last.downcase.to_sym
|
29
34
|
CONF_GLOBAL_SYM = :config
|
30
35
|
# old tool name
|
@@ -41,20 +46,28 @@ module Aspera
|
|
41
46
|
AOC_COMMAND_CURRENT=AOC_COMMAND_V3
|
42
47
|
CONNECT_WEB_URL = 'https://d3gcli72yxqn2z.cloudfront.net/connect'
|
43
48
|
CONNECT_VERSIONS = 'connectversions.js'
|
49
|
+
TRANSFER_SDK_ARCHIVE_URL = 'https://ibm.biz/aspera_sdk'
|
44
50
|
DEMO='demo'
|
51
|
+
DEMO_SERVER_PRESET='demoserver'
|
52
|
+
AOC_PATH_API_CLIENTS='admin/api-clients'
|
53
|
+
EMAIL_TEST_TEMPLATE=<<END_OF_TEMPLATE
|
54
|
+
From: <%=from_name%> <<%=from_email%>>
|
55
|
+
To: <<%=to%>>
|
56
|
+
Subject: Amelia email test
|
57
|
+
|
58
|
+
It worked !
|
59
|
+
END_OF_TEMPLATE
|
45
60
|
def option_preset; nil; end
|
46
61
|
|
47
62
|
def option_preset=(value)
|
48
63
|
self.options.add_option_preset(preset_by_name(value))
|
49
64
|
end
|
50
65
|
|
51
|
-
private_constant :
|
52
|
-
attr_accessor :option_ak_secret,:option_secrets
|
66
|
+
private_constant :DEFAULT_CONFIG_FILENAME,:CONF_PRESET_CONFIG,:CONF_PRESET_VERSION,:CONF_PRESET_DEFAULT,:CONF_PRESET_GLOBAL,:PROGRAM_NAME_V1,:PROGRAM_NAME_V2,:DEFAULT_REDIRECT,:ASPERA_PLUGINS_FOLDERNAME,:RUBY_FILE_EXT,:AOC_COMMAND_V1,:AOC_COMMAND_V2,:AOC_COMMAND_V3,:AOC_COMMAND_CURRENT,:DEMO,:TRANSFER_SDK_ARCHIVE_URL,:AOC_PATH_API_CLIENTS,:DEMO_SERVER_PRESET,:EMAIL_TEST_TEMPLATE
|
53
67
|
|
54
|
-
def initialize(env,tool_name,help_url,version)
|
68
|
+
def initialize(env,tool_name,help_url,version,main_folder)
|
55
69
|
super(env)
|
56
|
-
@
|
57
|
-
@option_secrets={}
|
70
|
+
raise 'missing secret manager' if @agents[:secret].nil?
|
58
71
|
@plugins={}
|
59
72
|
@plugin_lookup_folders=[]
|
60
73
|
@use_plugin_defaults=true
|
@@ -63,19 +76,11 @@ module Aspera
|
|
63
76
|
@program_version=version
|
64
77
|
@tool_name=tool_name
|
65
78
|
@help_url=help_url
|
66
|
-
|
67
|
-
if ENV.has_key?(tool_main_env_var)
|
68
|
-
@main_folder=ENV[tool_main_env_var]
|
69
|
-
else
|
70
|
-
user_home_folder=Dir.home
|
71
|
-
raise CliError,"Home folder does not exist: #{user_home_folder}. Check your user environment or use #{tool_main_env_var}." unless Dir.exist?(user_home_folder)
|
72
|
-
@main_folder=File.join(user_home_folder,ASPERA_HOME_FOLDER_NAME,tool_name)
|
73
|
-
end
|
79
|
+
@main_folder=main_folder
|
74
80
|
@conf_file_default=File.join(@main_folder,DEFAULT_CONFIG_FILENAME)
|
75
81
|
@option_config_file=@conf_file_default
|
76
82
|
Log.log.debug("#{tool_name} folder: #{@main_folder}")
|
77
83
|
# set folder for FASP SDK
|
78
|
-
Fasp::Installation.instance.folder=File.join(@main_folder,'sdk')
|
79
84
|
add_plugin_lookup_folder(File.join(@main_folder,ASPERA_PLUGINS_FOLDERNAME))
|
80
85
|
add_plugin_lookup_folder(self.class.gem_plugins_folder)
|
81
86
|
# do file parameter first
|
@@ -91,35 +96,76 @@ module Aspera
|
|
91
96
|
self.options.set_obj_attr(:ascp_path,self,:option_ascp_path)
|
92
97
|
self.options.set_obj_attr(:use_product,self,:option_use_product)
|
93
98
|
self.options.set_obj_attr(:preset,self,:option_preset)
|
94
|
-
self.options.set_obj_attr(:secret
|
95
|
-
self.options.set_obj_attr(:secrets
|
96
|
-
self.options.add_opt_boolean(:override,
|
97
|
-
self.options.add_opt_switch(:no_default,
|
99
|
+
self.options.set_obj_attr(:secret,@agents[:secret],:default_secret)
|
100
|
+
self.options.set_obj_attr(:secrets,@agents[:secret],:all_secrets)
|
101
|
+
self.options.add_opt_boolean(:override,'override existing value')
|
102
|
+
self.options.add_opt_switch(:no_default,'-N','do not load default configuration for plugin') { @use_plugin_defaults=false }
|
98
103
|
self.options.add_opt_boolean(:use_generic_client,'wizard: AoC: use global or org specific jwt client id')
|
99
|
-
self.options.add_opt_simple(:pkeypath,
|
100
|
-
self.options.add_opt_simple(:ascp_path,
|
101
|
-
self.options.add_opt_simple(:use_product,
|
102
|
-
self.options.add_opt_simple(:smtp,
|
103
|
-
self.options.add_opt_simple(:fpac,
|
104
|
-
self.options.add_opt_simple(:preset,
|
105
|
-
self.options.add_opt_simple(:default,
|
106
|
-
self.options.add_opt_simple(:secret,
|
107
|
-
self.options.add_opt_simple(:secrets,
|
108
|
-
self.options.
|
104
|
+
self.options.add_opt_simple(:pkeypath,'path to private key for JWT (wizard)')
|
105
|
+
self.options.add_opt_simple(:ascp_path,'path to ascp')
|
106
|
+
self.options.add_opt_simple(:use_product,'use ascp from specified product')
|
107
|
+
self.options.add_opt_simple(:smtp,'smtp configuration (extended value: hash)')
|
108
|
+
self.options.add_opt_simple(:fpac,'proxy auto configuration URL')
|
109
|
+
self.options.add_opt_simple(:preset,'-PVALUE','load the named option preset from current config file')
|
110
|
+
self.options.add_opt_simple(:default,'set as default configuration for specified plugin')
|
111
|
+
self.options.add_opt_simple(:secret,'default secret')
|
112
|
+
self.options.add_opt_simple(:secrets,'secret repository (Hash)')
|
113
|
+
self.options.add_opt_simple(:sdk_url,'URL to get SDK')
|
114
|
+
self.options.add_opt_simple(:sdk_folder,'SDK folder location')
|
115
|
+
self.options.add_opt_simple(:notif_to,'email recipient for notification of transfers')
|
116
|
+
self.options.add_opt_simple(:notif_template,'email ERB template for notification of transfers')
|
117
|
+
self.options.add_opt_boolean(:test_mode,'skip user validation in wizard mode')
|
118
|
+
self.options.add_opt_simple(:version_check_days,Integer,'period to check neew version in days (zero to disable)')
|
109
119
|
self.options.set_option(:use_generic_client,true)
|
110
120
|
self.options.set_option(:test_mode,false)
|
121
|
+
self.options.set_option(:version_check_days,7)
|
122
|
+
self.options.set_option(:sdk_url,TRANSFER_SDK_ARCHIVE_URL)
|
123
|
+
self.options.set_option(:sdk_folder,File.join(@main_folder,'sdk'))
|
111
124
|
self.options.parse_options!
|
112
|
-
raise CliBadArgument,
|
125
|
+
raise CliBadArgument,'secrets shall be Hash' unless @agents[:secret].all_secrets.is_a?(Hash)
|
126
|
+
Fasp::Installation.instance.folder=self.options.get_option(:sdk_folder,:mandatory)
|
113
127
|
end
|
114
128
|
|
115
|
-
def
|
116
|
-
|
117
|
-
|
118
|
-
|
129
|
+
def check_gem_version
|
130
|
+
this_gem_name=File.basename(File.dirname(self.class.gem_root)).gsub(/-[0-9].*$/,'')
|
131
|
+
latest_version=begin
|
132
|
+
Rest.new(base_url: 'https://rubygems.org/api/v1').read("versions/#{this_gem_name}/latest.json")[:data]['version']
|
133
|
+
rescue
|
134
|
+
Log.log.warn('Could not retrieve latest gem version on rubygems.')
|
135
|
+
'0'
|
136
|
+
end
|
137
|
+
return {name: this_gem_name, current: Aspera::Cli::VERSION, latest: latest_version, need_update: Gem::Version.new(Aspera::Cli::VERSION) < Gem::Version.new(latest_version)}
|
119
138
|
end
|
120
139
|
|
121
|
-
def
|
122
|
-
|
140
|
+
def periodic_check_newer_gem_version
|
141
|
+
# get verification period
|
142
|
+
delay_days=options.get_option(:version_check_days,:mandatory)
|
143
|
+
Log.log.info("check days: #{delay_days}")
|
144
|
+
# check only if not zero day
|
145
|
+
if !delay_days.eql?(0)
|
146
|
+
# get last date from persistency
|
147
|
+
last_check_array=[]
|
148
|
+
check_date_persist=PersistencyActionOnce.new(
|
149
|
+
manager: persistency,
|
150
|
+
data: last_check_array,
|
151
|
+
ids: ['version_last_check'])
|
152
|
+
# get persisted date or nil
|
153
|
+
last_check_date = begin
|
154
|
+
Date.strptime(last_check_array.first, '%Y/%m/%d')
|
155
|
+
rescue
|
156
|
+
nil
|
157
|
+
end
|
158
|
+
current_date=Date.today
|
159
|
+
Log.log.debug("days elapsed: #{last_check_date.is_a?(Date) ? current_date - last_check_date : last_check_date.class.name}")
|
160
|
+
if last_check_date.nil? or (current_date - last_check_date) > delay_days
|
161
|
+
last_check_array[0]=current_date.strftime('%Y/%m/%d')
|
162
|
+
check_date_persist.save
|
163
|
+
check_data=check_gem_version
|
164
|
+
if check_data[:need_update]
|
165
|
+
Log.log.warn("A new version is available: #{check_data[:latest]}. You have #{check_data[:current]}. Upgrade with: gem update #{check_data[:name]}")
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
123
169
|
end
|
124
170
|
|
125
171
|
# retrieve structure from cloud (CDN) with all versions available
|
@@ -155,7 +201,7 @@ module Aspera
|
|
155
201
|
require 'openssl'
|
156
202
|
priv_key = OpenSSL::PKey::RSA.new(4096)
|
157
203
|
File.write(private_key_path,priv_key.to_s)
|
158
|
-
File.write(private_key_path+
|
204
|
+
File.write(private_key_path+'.pub',priv_key.public_key.to_s)
|
159
205
|
nil
|
160
206
|
end
|
161
207
|
|
@@ -181,7 +227,7 @@ module Aspera
|
|
181
227
|
r=[]
|
182
228
|
t.each do |k,v|
|
183
229
|
v.each do |kk,vv|
|
184
|
-
r.push({
|
230
|
+
r.push({'config'=>k,'parameter'=>kk,'value'=>vv})
|
185
231
|
end
|
186
232
|
end
|
187
233
|
return r
|
@@ -191,12 +237,12 @@ module Aspera
|
|
191
237
|
# creates one if none already created
|
192
238
|
# @return preset that contains global default
|
193
239
|
def set_global_default(key,value)
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
@config_presets[global_default_preset_name]={}
|
198
|
-
end
|
240
|
+
# get default preset if it exists
|
241
|
+
global_default_preset_name=get_plugin_default_config_name(CONF_GLOBAL_SYM) || CONF_PRESET_GLOBAL
|
242
|
+
@config_presets[global_default_preset_name]||={}
|
199
243
|
@config_presets[global_default_preset_name][key.to_s]=value
|
244
|
+
self.format.display_status("Updated: #{global_default_preset_name}: #{key} <- #{value}")
|
245
|
+
save_presets_to_config_file
|
200
246
|
return global_default_preset_name
|
201
247
|
end
|
202
248
|
|
@@ -215,7 +261,7 @@ module Aspera
|
|
215
261
|
# @return the hash from name (also expands possible includes)
|
216
262
|
def preset_by_name(config_name, include_path=[])
|
217
263
|
raise CliError,"no such config preset: #{config_name}" unless @config_presets.has_key?(config_name)
|
218
|
-
raise CliError,
|
264
|
+
raise CliError,'loop in include' if include_path.include?(config_name)
|
219
265
|
return expanded_with_preset_includes(@config_presets[config_name],include_path.clone.push(config_name))
|
220
266
|
end
|
221
267
|
|
@@ -250,7 +296,7 @@ module Aspera
|
|
250
296
|
end
|
251
297
|
|
252
298
|
def option_use_product
|
253
|
-
|
299
|
+
'write-only value'
|
254
300
|
end
|
255
301
|
|
256
302
|
def convert_preset_path(old_name,new_name,files_to_copy)
|
@@ -294,22 +340,21 @@ module Aspera
|
|
294
340
|
# if no file found, create default config
|
295
341
|
if conf_file_to_load.nil?
|
296
342
|
Log.log.warn("No config file found. Creating empty configuration file: #{@option_config_file}")
|
297
|
-
@config_presets={CONF_PRESET_CONFIG=>{CONF_PRESET_VERSION=>@program_version}
|
298
|
-
'demoserver'=>{'url'=>'ssh://'+DEMO+'.asperasoft.com:33001','username'=>AOC_COMMAND_V2,'ssAP'.downcase.reverse+'drow'.reverse=>DEMO+AOC_COMMAND_V2}}
|
343
|
+
@config_presets={CONF_PRESET_CONFIG=>{CONF_PRESET_VERSION=>@program_version}}
|
299
344
|
else
|
300
345
|
Log.log.debug "loading #{@option_config_file}"
|
301
346
|
@config_presets=YAML.load_file(conf_file_to_load)
|
302
347
|
end
|
303
348
|
files_to_copy=[]
|
304
349
|
Log.log.debug "Available_presets: #{@config_presets}"
|
305
|
-
raise
|
350
|
+
raise 'Expecting YAML Hash' unless @config_presets.is_a?(Hash)
|
306
351
|
# check there is at least the config section
|
307
352
|
if !@config_presets.has_key?(CONF_PRESET_CONFIG)
|
308
353
|
raise "Cannot find key: #{CONF_PRESET_CONFIG}"
|
309
354
|
end
|
310
355
|
version=@config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]
|
311
356
|
if version.nil?
|
312
|
-
raise
|
357
|
+
raise 'No version found in config section.'
|
313
358
|
end
|
314
359
|
# oldest compatible conf file format, update to latest version when an incompatible change is made
|
315
360
|
# check compatibility of version of conf file
|
@@ -338,24 +383,24 @@ module Aspera
|
|
338
383
|
end
|
339
384
|
# Place new compatibility code here
|
340
385
|
if save_required
|
341
|
-
Log.log.warn(
|
386
|
+
Log.log.warn('Saving automatic conversion.')
|
342
387
|
@config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]=@program_version
|
343
388
|
save_presets_to_config_file
|
344
|
-
Log.log.warn(
|
389
|
+
Log.log.warn('Copying referenced files')
|
345
390
|
files_to_copy.each do |file|
|
346
391
|
FileUtils.cp(file,@main_folder)
|
347
392
|
Log.log.warn("..#{file} -> #{@main_folder}")
|
348
393
|
end
|
349
394
|
end
|
350
395
|
rescue Psych::SyntaxError => e
|
351
|
-
Log.log.error(
|
396
|
+
Log.log.error('YAML error in config file')
|
352
397
|
raise e
|
353
398
|
rescue => e
|
354
399
|
Log.log.debug("-> #{e}")
|
355
400
|
new_name="#{@option_config_file}.pre#{@program_version}.manual_conversion_needed"
|
356
401
|
File.rename(@option_config_file,new_name)
|
357
402
|
Log.log.warn("Renamed config file to #{new_name}.")
|
358
|
-
Log.log.warn(
|
403
|
+
Log.log.warn('Manual Conversion is required. Next time, a new empty file will be created.')
|
359
404
|
raise CliError,e.to_s
|
360
405
|
end
|
361
406
|
end
|
@@ -420,10 +465,10 @@ module Aspera
|
|
420
465
|
fileurl = one_link['href']
|
421
466
|
filename=fileurl.gsub(%r{.*/},'')
|
422
467
|
api_connect_cdn.call({:operation=>'GET',:subpath=>fileurl,:save_to_file=>File.join(folder_dest,filename)})
|
423
|
-
return Main.result_status("
|
468
|
+
return Main.result_status("Downloaded: #{filename}")
|
424
469
|
when :open #
|
425
470
|
OpenApplication.instance.uri(one_link['href'])
|
426
|
-
return Main.result_status("
|
471
|
+
return Main.result_status("Opened: #{one_link['href']}")
|
427
472
|
end
|
428
473
|
end
|
429
474
|
end
|
@@ -431,29 +476,29 @@ module Aspera
|
|
431
476
|
end
|
432
477
|
|
433
478
|
def execute_action_ascp
|
434
|
-
command=self.options.get_next_command([:connect,:use,:show,:products,:info,:install])
|
479
|
+
command=self.options.get_next_command([:connect,:use,:show,:products,:info,:install,:spec])
|
435
480
|
case command
|
436
481
|
when :connect
|
437
482
|
return execute_connect_action
|
438
483
|
when :use
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
preset_name
|
444
|
-
save_presets_to_config_file
|
445
|
-
return {:type=>:status, :data=>"saved to default global preset #{preset_name}"}
|
484
|
+
ascp_path=self.options.get_next_argument('path to ascp')
|
485
|
+
ascp_version=Fasp::Installation.instance.get_ascp_version(ascp_path)
|
486
|
+
self.format.display_status("ascp version: #{ascp_version}")
|
487
|
+
preset_name=set_global_default(:ascp_path,ascp_path)
|
488
|
+
return Main.result_status("Saved to default global preset #{preset_name}")
|
446
489
|
when :show # shows files used
|
447
490
|
return {:type=>:status, :data=>Fasp::Installation.instance.path(:ascp)}
|
448
491
|
when :info # shows files used
|
449
492
|
data=Fasp::Installation::FILES.inject({}) do |m,v|
|
450
|
-
m[v.to_s]=Fasp::Installation.instance.path(v) rescue
|
493
|
+
m[v.to_s]=Fasp::Installation.instance.path(v) rescue 'Not Found'
|
451
494
|
m
|
452
495
|
end
|
453
496
|
# read PATHs from ascp directly, and pvcl modules as well
|
454
497
|
Open3.popen3(Fasp::Installation.instance.path(:ascp),'-DDL-') do |stdin, stdout, stderr, thread|
|
498
|
+
last_line=''
|
455
499
|
while line=stderr.gets do
|
456
500
|
line.chomp!
|
501
|
+
last_line=line
|
457
502
|
case line
|
458
503
|
when %r{^DBG Path ([^ ]+) (dir|file) +: (.*)$};data[$1]=$3
|
459
504
|
when %r{^DBG Added module group:"([^"]+)" name:"([^"]+)", version:"([^"]+)" interface:"([^"]+)"$};data[$2]=$4
|
@@ -462,6 +507,9 @@ module Aspera
|
|
462
507
|
when %r{^LOG Initializing FASP version ([^,]+),};data['ascp_version']=$1
|
463
508
|
end
|
464
509
|
end
|
510
|
+
if !thread.value.exitstatus.eql?(1) and !data.has_key?('root')
|
511
|
+
raise last_line
|
512
|
+
end
|
465
513
|
end
|
466
514
|
data['keypass']=Fasp::Installation.instance.bypass_pass
|
467
515
|
return {:type=>:single_object, :data=>data}
|
@@ -474,17 +522,18 @@ module Aspera
|
|
474
522
|
default_product=self.options.get_next_argument('product name')
|
475
523
|
Fasp::Installation.instance.use_ascp_from_product(default_product)
|
476
524
|
preset_name=set_global_default(:ascp_path,Fasp::Installation.instance.path(:ascp))
|
477
|
-
|
478
|
-
return {:type=>:status, :data=>"saved to default global preset #{preset_name}"}
|
525
|
+
return Main.result_status("Saved to default global preset #{preset_name}")
|
479
526
|
end
|
480
527
|
when :install
|
481
|
-
v=Fasp::Installation.instance.install_sdk
|
482
|
-
return
|
528
|
+
v=Fasp::Installation.instance.install_sdk(self.options.get_option(:sdk_url,:mandatory))
|
529
|
+
return Main.result_status("Installed version #{v}")
|
530
|
+
when :spec
|
531
|
+
return {type: :object_list, data: Fasp::Parameters.man_table, fields: ['name','type',Fasp::Parameters::SUPPORTED_AGENTS_SHORT.map{|i|i.to_s},'description'].flatten}
|
483
532
|
end
|
484
533
|
raise "unexpected case: #{command}"
|
485
534
|
end
|
486
535
|
|
487
|
-
ACTIONS=[:gem_path, :genkey,:plugins,:flush_tokens,:list,:overview,:open,:echo,:id,:documentation,:wizard,:export_to_cli,:detect,:coffee,:ascp,:email_test,:smtp_settings,:proxy_check,:folder,:file]
|
536
|
+
ACTIONS=[:gem_path, :genkey,:plugins,:flush_tokens,:list,:overview,:open,:echo,:id,:documentation,:wizard,:export_to_cli,:detect,:coffee,:ascp,:email_test,:smtp_settings,:proxy_check,:folder,:file,:check_update,:initdemo]
|
488
537
|
|
489
538
|
# "config" plugin
|
490
539
|
def execute_action
|
@@ -503,7 +552,7 @@ module Aspera
|
|
503
552
|
when :delete
|
504
553
|
@config_presets.delete(config_name)
|
505
554
|
save_presets_to_config_file
|
506
|
-
return Main.result_status("
|
555
|
+
return Main.result_status("Deleted: #{config_name}")
|
507
556
|
when :get
|
508
557
|
param_name=self.options.get_next_argument('parameter name')
|
509
558
|
value=selected_preset[param_name]
|
@@ -516,7 +565,7 @@ module Aspera
|
|
516
565
|
param_name=self.options.get_next_argument('parameter name')
|
517
566
|
selected_preset.delete(param_name)
|
518
567
|
save_presets_to_config_file
|
519
|
-
return Main.result_status("
|
568
|
+
return Main.result_status("Removed: #{config_name}: #{param_name}")
|
520
569
|
when :set
|
521
570
|
param_name=self.options.get_next_argument('parameter name')
|
522
571
|
param_value=self.options.get_next_argument('parameter value')
|
@@ -529,7 +578,7 @@ module Aspera
|
|
529
578
|
end
|
530
579
|
selected_preset[param_name]=param_value
|
531
580
|
save_presets_to_config_file
|
532
|
-
return Main.result_status("
|
581
|
+
return Main.result_status("Updated: #{config_name}: #{param_name} <- #{param_value}")
|
533
582
|
when :initialize
|
534
583
|
config_value=self.options.get_next_argument('extended value (Hash)')
|
535
584
|
if @config_presets.has_key?(config_name)
|
@@ -537,7 +586,7 @@ module Aspera
|
|
537
586
|
end
|
538
587
|
@config_presets[config_name]=config_value
|
539
588
|
save_presets_to_config_file
|
540
|
-
return Main.result_status("
|
589
|
+
return Main.result_status("Modified: #{@option_config_file}")
|
541
590
|
when :update
|
542
591
|
default_for_plugin=self.options.get_option(:default,:optional)
|
543
592
|
# get unprocessed options
|
@@ -550,7 +599,7 @@ module Aspera
|
|
550
599
|
@config_presets[CONF_PRESET_DEFAULT][default_for_plugin]=config_name
|
551
600
|
end
|
552
601
|
save_presets_to_config_file
|
553
|
-
return Main.result_status("
|
602
|
+
return Main.result_status("Updated: #{config_name}")
|
554
603
|
when :ask
|
555
604
|
self.options.ask_missing_mandatory=:yes
|
556
605
|
@config_presets[config_name]||={}
|
@@ -559,10 +608,12 @@ module Aspera
|
|
559
608
|
@config_presets[config_name][optionname]=option_value
|
560
609
|
end
|
561
610
|
save_presets_to_config_file
|
562
|
-
return Main.result_status("
|
611
|
+
return Main.result_status("Updated: #{config_name}")
|
563
612
|
end
|
564
613
|
when :documentation
|
565
|
-
|
614
|
+
section=options.get_next_argument('private key file path',:single,:optional)
|
615
|
+
section='#'+section unless section.nil?
|
616
|
+
OpenApplication.instance.uri("#{@help_url}#{section}")
|
566
617
|
return Main.result_nothing
|
567
618
|
when :open
|
568
619
|
OpenApplication.instance.uri("#{@option_config_file}") #file://
|
@@ -570,9 +621,9 @@ module Aspera
|
|
570
621
|
when :genkey # generate new rsa key
|
571
622
|
private_key_path=self.options.get_next_argument('private key file path')
|
572
623
|
generate_new_key(private_key_path)
|
573
|
-
return Main.result_status('
|
624
|
+
return Main.result_status('Generated key: '+private_key_path)
|
574
625
|
when :echo # display the content of a value given on command line
|
575
|
-
result={:type=>:other_struct, :data=>self.options.get_next_argument(
|
626
|
+
result={:type=>:other_struct, :data=>self.options.get_next_argument('value')}
|
576
627
|
# special for csv
|
577
628
|
result[:type]=:object_list if result[:data].is_a?(Array) and result[:data].first.is_a?(Hash)
|
578
629
|
return result
|
@@ -587,14 +638,13 @@ module Aspera
|
|
587
638
|
return {:type=>:object_list,:data=>self.class.flatten_all_config(@config_presets)}
|
588
639
|
when :wizard
|
589
640
|
self.options.ask_missing_mandatory=true
|
590
|
-
#self.options.set_option(:interactive,:yes)
|
591
641
|
# register url option
|
592
642
|
BasicAuthPlugin.new(@agents.merge(skip_option_header: true))
|
593
643
|
instance_url=self.options.get_option(:url,:mandatory)
|
594
644
|
appli=ApiDetector.discover_product(instance_url)
|
595
645
|
case appli[:product]
|
596
646
|
when :aoc
|
597
|
-
self.format.display_status(
|
647
|
+
self.format.display_status('Detected: Aspera on Cloud'.bold)
|
598
648
|
organization,instance_domain=AoC.parse_url(instance_url)
|
599
649
|
aspera_preset_name='aoc_'+organization
|
600
650
|
self.format.display_status("Preparing preset: #{aspera_preset_name}")
|
@@ -608,7 +658,7 @@ module Aspera
|
|
608
658
|
private_key_path=self.options.get_option(:pkeypath,:optional)
|
609
659
|
# give a chance to provide
|
610
660
|
if private_key_path.nil?
|
611
|
-
self.format.display_status(
|
661
|
+
self.format.display_status('Please provide path to your private RSA key, or empty to generate one:')
|
612
662
|
private_key_path=self.options.get_option(:pkeypath,:mandatory).to_s
|
613
663
|
end
|
614
664
|
# else generate path
|
@@ -616,69 +666,69 @@ module Aspera
|
|
616
666
|
private_key_path=File.join(@main_folder,'aspera_aoc_key')
|
617
667
|
end
|
618
668
|
if File.exist?(private_key_path)
|
619
|
-
self.format.display_status(
|
669
|
+
self.format.display_status('Using existing key:')
|
620
670
|
else
|
621
|
-
self.format.display_status(
|
671
|
+
self.format.display_status('Generating key...')
|
622
672
|
generate_new_key(private_key_path)
|
623
|
-
self.format.display_status(
|
673
|
+
self.format.display_status('Created:')
|
624
674
|
end
|
625
675
|
self.format.display_status("#{private_key_path}")
|
626
676
|
pub_key_pem=OpenSSL::PKey::RSA.new(File.read(private_key_path)).public_key.to_s
|
627
|
-
#
|
677
|
+
# declare command line options for AoC
|
628
678
|
require 'aspera/cli/plugins/aoc'
|
629
679
|
# make username mandatory for jwt, this triggers interactive input
|
630
680
|
self.options.get_option(:username,:mandatory)
|
631
|
-
# instanciate AoC plugin
|
681
|
+
# instanciate AoC plugin, so that command line options are known
|
632
682
|
files_plugin=self.class.plugin_new(AOC_COMMAND_CURRENT,@agents.merge({skip_basic_auth_options: true, private_key_path: private_key_path}))
|
683
|
+
aoc_api=files_plugin.get_api
|
633
684
|
auto_set_pub_key=false
|
634
685
|
auto_set_jwt=false
|
635
686
|
use_browser_authentication=false
|
636
687
|
if self.options.get_option(:use_generic_client)
|
637
|
-
self.format.display_status(
|
638
|
-
self.format.display_status(
|
639
|
-
self.format.display_status(
|
640
|
-
self.format.display_status(
|
688
|
+
self.format.display_status('Using global client_id.')
|
689
|
+
self.format.display_status('Please Login to your Aspera on Cloud instance.'.red)
|
690
|
+
self.format.display_status('Navigate to your "Account Settings"'.red)
|
691
|
+
self.format.display_status('Check or update the value of "Public Key" to be:'.red.blink)
|
641
692
|
self.format.display_status("#{pub_key_pem}")
|
642
693
|
if ! self.options.get_option(:test_mode)
|
643
|
-
self.format.display_status(
|
694
|
+
self.format.display_status('Once updated or validated, press enter.')
|
644
695
|
OpenApplication.instance.uri(instance_url)
|
645
696
|
STDIN.gets
|
646
697
|
end
|
647
698
|
else
|
648
|
-
self.format.display_status(
|
699
|
+
self.format.display_status('Using organization specific client_id.')
|
649
700
|
if self.options.get_option(:client_id,:optional).nil? or self.options.get_option(:client_secret,:optional).nil?
|
650
|
-
self.format.display_status(
|
651
|
-
self.format.display_status(
|
652
|
-
self.format.display_status(
|
701
|
+
self.format.display_status('Please login to your Aspera on Cloud instance.'.red)
|
702
|
+
self.format.display_status('Go to: Apps->Admin->Organization->Integrations')
|
703
|
+
self.format.display_status('Create or check if there is an existing integration named:')
|
653
704
|
self.format.display_status("- name: #{@tool_name}")
|
654
705
|
self.format.display_status("- redirect uri: #{DEFAULT_REDIRECT}")
|
655
|
-
self.format.display_status(
|
656
|
-
self.format.display_status(
|
657
|
-
self.format.display_status(
|
706
|
+
self.format.display_status('- origin: localhost')
|
707
|
+
self.format.display_status('Once created or identified,')
|
708
|
+
self.format.display_status('Please enter:'.red)
|
658
709
|
end
|
659
|
-
OpenApplication.instance.uri(instance_url
|
710
|
+
OpenApplication.instance.uri("#{instance_url}/#{AOC_PATH_API_CLIENTS}")
|
660
711
|
self.options.get_option(:client_id,:mandatory)
|
661
712
|
self.options.get_option(:client_secret,:mandatory)
|
662
713
|
use_browser_authentication=true
|
663
714
|
end
|
664
715
|
if use_browser_authentication
|
665
|
-
self.format.display_status(
|
666
|
-
self.options.set_option(:auth,:web)
|
667
|
-
self.options.set_option(:redirect_uri,DEFAULT_REDIRECT)
|
716
|
+
self.format.display_status('We will use web authentication to bootstrap.')
|
668
717
|
auto_set_pub_key=true
|
669
718
|
auto_set_jwt=true
|
670
|
-
|
719
|
+
@api_aoc.oauth.params[:auth]=:web
|
720
|
+
@api_aoc.oauth.params[:redirect_uri]=DEFAULT_REDIRECT
|
721
|
+
@api_aoc.oauth.params[:scope]=AoC::SCOPE_FILES_ADMIN
|
671
722
|
end
|
672
|
-
|
673
|
-
myself=files_plugin.api_aoc.read('self')[:data]
|
723
|
+
myself=aoc_api.read('self')[:data]
|
674
724
|
if auto_set_pub_key
|
675
|
-
raise CliError,
|
676
|
-
self.format.display_status(
|
677
|
-
|
725
|
+
raise CliError,'public key is already set in profile (use --override=yes)' unless myself['public_key'].empty? or option_override
|
726
|
+
self.format.display_status('Updating profile with new key')
|
727
|
+
aoc_api.update("users/#{myself['id']}",{'public_key'=>pub_key_pem})
|
678
728
|
end
|
679
729
|
if auto_set_jwt
|
680
|
-
self.format.display_status(
|
681
|
-
|
730
|
+
self.format.display_status('Enabling JWT for client')
|
731
|
+
aoc_api.update("clients/#{self.options.get_option(:client_id)}",{'jwt_grant_enabled'=>true,'explicit_authorization_required'=>false})
|
682
732
|
end
|
683
733
|
self.format.display_status("creating new config preset: #{aspera_preset_name}")
|
684
734
|
@config_presets[aspera_preset_name]={
|
@@ -694,14 +744,14 @@ module Aspera
|
|
694
744
|
end
|
695
745
|
self.format.display_status("Setting config preset as default for #{AOC_COMMAND_CURRENT}")
|
696
746
|
@config_presets[CONF_PRESET_DEFAULT][AOC_COMMAND_CURRENT]=aspera_preset_name
|
697
|
-
self.format.display_status(
|
747
|
+
self.format.display_status('saving config file')
|
698
748
|
save_presets_to_config_file
|
699
749
|
return Main.result_status("Done.\nYou can test with:\n#{@tool_name} #{AOC_COMMAND_CURRENT} user info show")
|
700
750
|
else
|
701
751
|
raise CliBadArgument,"Supports only: aoc. Detected: #{appli}"
|
702
752
|
end
|
703
753
|
when :export_to_cli
|
704
|
-
self.format.display_status(
|
754
|
+
self.format.display_status('Exporting: Aspera on Cloud')
|
705
755
|
require 'aspera/cli/plugins/aoc'
|
706
756
|
# need url / username
|
707
757
|
add_plugin_default_preset(AOC_COMMAND_V3.to_sym)
|
@@ -734,11 +784,11 @@ module Aspera
|
|
734
784
|
entry.merge!(new_conf)
|
735
785
|
end
|
736
786
|
File.write(cli_conf_file,JSON.pretty_generate(data))
|
737
|
-
return Main.result_status("
|
787
|
+
return Main.result_status("Updated: #{cli_conf_file}")
|
738
788
|
when :detect
|
739
789
|
# need url / username
|
740
790
|
BasicAuthPlugin.new(@agents)
|
741
|
-
return Main.result_status("
|
791
|
+
return Main.result_status("Found: #{ApiDetector.discover_product(self.options.get_option(:url,:mandatory))}")
|
742
792
|
when :coffee
|
743
793
|
OpenApplication.instance.uri('https://enjoyjava.com/wp-content/uploads/2018/01/How-to-make-strong-coffee.jpg')
|
744
794
|
return Main.result_nothing
|
@@ -751,26 +801,41 @@ module Aspera
|
|
751
801
|
when :file
|
752
802
|
return Main.result_status(@option_config_file)
|
753
803
|
when :email_test
|
754
|
-
|
755
|
-
send_email({
|
756
|
-
to: dest_email,
|
757
|
-
subject: 'Amelia email test',
|
758
|
-
body: 'It worked !',
|
759
|
-
})
|
804
|
+
send_email_template({},EMAIL_TEST_TEMPLATE)
|
760
805
|
return Main.result_nothing
|
761
806
|
when :smtp_settings
|
762
807
|
return {:type=>:single_object,:data=>email_settings}
|
763
808
|
when :proxy_check
|
764
809
|
pac_url=self.options.get_option(:fpac,:mandatory)
|
765
|
-
server_url=self.options.get_next_argument(
|
810
|
+
server_url=self.options.get_next_argument('server url')
|
766
811
|
return Main.result_status(Aspera::ProxyAutoConfig.new(UriReader.read(pac_url)).get_proxy(server_url))
|
767
|
-
|
812
|
+
when :check_update
|
813
|
+
return {:type=>:single_object, :data=>check_gem_version}
|
814
|
+
when :initdemo
|
815
|
+
if @config_presets.has_key?(DEMO_SERVER_PRESET)
|
816
|
+
Log.log.warn("Demo server preset already present: #{DEMO_SERVER_PRESET}")
|
817
|
+
else
|
818
|
+
Log.log.info("Creating Demo server preset: #{DEMO_SERVER_PRESET}")
|
819
|
+
@config_presets[DEMO_SERVER_PRESET]={'url'=>'ssh://'+DEMO+'.asperasoft.com:33001','username'=>AOC_COMMAND_V2,'ssAP'.downcase.reverse+'drow'.reverse=>DEMO+AOC_COMMAND_V2}
|
820
|
+
end
|
821
|
+
@config_presets[CONF_PRESET_DEFAULT]||={}
|
822
|
+
if @config_presets[CONF_PRESET_DEFAULT].has_key?('server')
|
823
|
+
Log.log.warn("server default preset already set to: #{@config_presets[CONF_PRESET_DEFAULT]['server']}")
|
824
|
+
Log.log.warn("use #{DEMO_SERVER_PRESET} for demo: -P#{DEMO_SERVER_PRESET}") unless DEMO_SERVER_PRESET.eql?(@config_presets[CONF_PRESET_DEFAULT]['server'])
|
825
|
+
else
|
826
|
+
@config_presets[CONF_PRESET_DEFAULT]['server']=DEMO_SERVER_PRESET
|
827
|
+
Log.log.info("setting server default preset to : #{DEMO_SERVER_PRESET}")
|
828
|
+
end
|
829
|
+
save_presets_to_config_file
|
830
|
+
return Main.result_status("Done")
|
831
|
+
else raise 'error'
|
768
832
|
end
|
769
833
|
end
|
770
834
|
|
835
|
+
# @return email server setting with defaults if not defined
|
771
836
|
def email_settings
|
772
837
|
smtp=self.options.get_option(:smtp,:mandatory)
|
773
|
-
# change string keys into
|
838
|
+
# change string keys into symbol keys
|
774
839
|
smtp=smtp.keys.inject({}){|m,v|m[v.to_sym]=smtp[v];m}
|
775
840
|
# defaults
|
776
841
|
smtp[:tls]||=true
|
@@ -780,39 +845,47 @@ module Aspera
|
|
780
845
|
smtp[:domain]||=smtp[:from_email].gsub(/^.*@/,'') if smtp.has_key?(:from_email)
|
781
846
|
# check minimum required
|
782
847
|
[:server,:port,:domain].each do |n|
|
783
|
-
raise "
|
848
|
+
raise "Missing smtp parameter: #{n}" unless smtp.has_key?(n)
|
784
849
|
end
|
785
850
|
Log.log.debug("smtp=#{smtp}")
|
786
851
|
return smtp
|
787
852
|
end
|
788
853
|
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
854
|
+
# create a clean binding (ruby variable environment)
|
855
|
+
def empty_binding
|
856
|
+
Kernel.binding
|
857
|
+
end
|
858
|
+
|
859
|
+
def send_email_template(vars,email_template_default=nil)
|
860
|
+
vars[:to]||=options.get_option(:notif_to,:mandatory)
|
861
|
+
notif_template=options.get_option(:notif_template,email_template_default.nil? ? :mandatory : :optional) || email_template_default
|
862
|
+
mail_conf=email_settings
|
863
|
+
vars[:from_name]||=mail_conf[:from_name]
|
864
|
+
vars[:from_email]||=mail_conf[:from_email]
|
865
|
+
[:from_name,:from_email].each do |n|
|
866
|
+
raise "Missing email parameter: #{n}" unless vars.has_key?(n)
|
867
|
+
end
|
868
|
+
start_options=[mail_conf[:domain]]
|
869
|
+
start_options.push(mail_conf[:username],mail_conf[:password],:login) if mail_conf.has_key?(:username) and mail_conf.has_key?(:password)
|
870
|
+
# create a binding with only variables defined in vars
|
871
|
+
template_binding=empty_binding
|
872
|
+
# add variables to binding
|
873
|
+
vars.each do |k,v|
|
874
|
+
raise "key (#{k.class}) must be Symbol" unless k.is_a?(Symbol)
|
875
|
+
template_binding.local_variable_set(k,v)
|
796
876
|
end
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
#{email[:body]}
|
803
|
-
END_OF_MESSAGE
|
804
|
-
start_options=[opts[:domain]]
|
805
|
-
start_options.push(opts[:username],opts[:password],:login) if opts.has_key?(:username) and opts.has_key?(:password)
|
806
|
-
|
807
|
-
smtp = Net::SMTP.new(opts[:server], opts[:port])
|
808
|
-
smtp.enable_starttls if opts[:tls]
|
877
|
+
# execute template
|
878
|
+
msg_with_headers=ERB.new(notif_template).result(template_binding)
|
879
|
+
Log.dump(:msg_with_headers,msg_with_headers)
|
880
|
+
smtp = Net::SMTP.new(mail_conf[:server], mail_conf[:port])
|
881
|
+
smtp.enable_starttls if mail_conf[:tls]
|
809
882
|
smtp.start(*start_options) do |smtp|
|
810
|
-
smtp.send_message(
|
883
|
+
smtp.send_message(msg_with_headers, vars[:from_email], vars[:to])
|
811
884
|
end
|
812
885
|
end
|
813
886
|
|
814
887
|
def save_presets_to_config_file
|
815
|
-
raise
|
888
|
+
raise 'no configuration loaded' if @config_presets.nil?
|
816
889
|
FileUtils.mkdir_p(@main_folder) unless Dir.exist?(@main_folder)
|
817
890
|
Log.log.debug "writing #{@option_config_file}"
|
818
891
|
File.write(@option_config_file,@config_presets.to_yaml)
|
@@ -823,7 +896,7 @@ END_OF_MESSAGE
|
|
823
896
|
def get_plugin_default_config_name(plugin_sym)
|
824
897
|
raise "internal error: config_presets shall be defined" if @config_presets.nil?
|
825
898
|
if !@use_plugin_defaults
|
826
|
-
Log.log.debug(
|
899
|
+
Log.log.debug('skip default config')
|
827
900
|
return nil
|
828
901
|
end
|
829
902
|
if @config_presets.has_key?(CONF_PRESET_DEFAULT) and
|