aspera-cli 4.0.0 → 4.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|