aspera-cli 4.0.0.pre2 → 4.2.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +761 -210
  3. data/bin/ascli +2 -0
  4. data/bin/dascli +13 -0
  5. data/docs/Makefile +2 -1
  6. data/docs/README.erb.md +628 -160
  7. data/docs/test_env.conf +22 -10
  8. data/docs/transfer_spec.html +1 -1
  9. data/lib/aspera/aoc.rb +87 -108
  10. data/lib/aspera/cli/formater.rb +2 -0
  11. data/lib/aspera/cli/main.rb +48 -45
  12. data/lib/aspera/cli/manager.rb +19 -6
  13. data/lib/aspera/cli/plugin.rb +9 -4
  14. data/lib/aspera/cli/plugins/alee.rb +1 -1
  15. data/lib/aspera/cli/plugins/aoc.rb +208 -183
  16. data/lib/aspera/cli/plugins/ats.rb +2 -2
  17. data/lib/aspera/cli/plugins/config.rb +205 -125
  18. data/lib/aspera/cli/plugins/console.rb +2 -2
  19. data/lib/aspera/cli/plugins/faspex.rb +15 -8
  20. data/lib/aspera/cli/plugins/faspex5.rb +76 -37
  21. data/lib/aspera/cli/plugins/node.rb +3 -3
  22. data/lib/aspera/cli/plugins/preview.rb +35 -25
  23. data/lib/aspera/cli/plugins/server.rb +23 -8
  24. data/lib/aspera/cli/transfer_agent.rb +7 -6
  25. data/lib/aspera/cli/version.rb +1 -1
  26. data/lib/aspera/colors.rb +5 -1
  27. data/lib/aspera/cos_node.rb +33 -28
  28. data/lib/aspera/environment.rb +15 -4
  29. data/lib/aspera/fasp/connect.rb +28 -21
  30. data/lib/aspera/fasp/http_gw.rb +140 -28
  31. data/lib/aspera/fasp/installation.rb +119 -57
  32. data/lib/aspera/fasp/local.rb +174 -178
  33. data/lib/aspera/fasp/manager.rb +12 -0
  34. data/lib/aspera/fasp/node.rb +4 -4
  35. data/lib/aspera/fasp/parameters.rb +6 -18
  36. data/lib/aspera/fasp/resume_policy.rb +13 -12
  37. data/lib/aspera/log.rb +10 -2
  38. data/lib/aspera/node.rb +61 -1
  39. data/lib/aspera/oauth.rb +36 -13
  40. data/lib/aspera/persistency_folder.rb +9 -4
  41. data/lib/aspera/preview/file_types.rb +53 -21
  42. data/lib/aspera/preview/generator.rb +3 -3
  43. data/lib/aspera/rest.rb +29 -18
  44. data/lib/aspera/secrets.rb +20 -0
  45. data/lib/aspera/temp_file_manager.rb +19 -0
  46. metadata +40 -22
@@ -107,7 +107,7 @@ module Aspera
107
107
  :auth => {
108
108
  :type => :basic,
109
109
  :username => access_key_id,
110
- :password => self.config.get_secret(access_key_id)}})
110
+ :password => @agents[:secret].get_secret(access_key_id)}})
111
111
  command=self.options.get_next_command(Node::COMMON_ACTIONS)
112
112
  return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_node)).execute_action(command)
113
113
  when :cluster
@@ -116,7 +116,7 @@ module Aspera
116
116
  :auth => {
117
117
  :type => :basic,
118
118
  :username => access_key_id,
119
- :password => self.config.get_secret(access_key_id)
119
+ :password => @agents[:secret].get_secret(access_key_id)
120
120
  }}
121
121
  api_ak_auth=Rest.new(rest_params)
122
122
  return {:type=>:single_object, :data=>api_ak_auth.read("servers")[:data]}
@@ -7,10 +7,12 @@ require 'aspera/aoc'
7
7
  require 'aspera/proxy_auto_config'
8
8
  require 'aspera/uri_reader'
9
9
  require 'aspera/rest'
10
+ require 'aspera/persistency_action_once'
10
11
  require 'xmlsimple'
11
12
  require 'base64'
12
13
  require 'net/smtp'
13
14
  require 'open3'
15
+ require 'date'
14
16
 
15
17
  module Aspera
16
18
  module Cli
@@ -25,6 +27,7 @@ module Aspera
25
27
  CONF_PRESET_CONFIG='config'
26
28
  CONF_PRESET_VERSION='version'
27
29
  CONF_PRESET_DEFAULT='default'
30
+ CONF_PRESET_GLOBAL='global_common_defaults'
28
31
  CONF_PLUGIN_SYM = :config # Plugins::Config.name.split('::').last.downcase.to_sym
29
32
  CONF_GLOBAL_SYM = :config
30
33
  # old tool name
@@ -32,10 +35,8 @@ module Aspera
32
35
  PROGRAM_NAME_V2 = 'mlia'
33
36
  # default redirect for AoC web auth
34
37
  DEFAULT_REDIRECT='http://localhost:12345'
35
- # folder containing custom plugins in `main_folder`
38
+ # folder containing custom plugins in user's config folder
36
39
  ASPERA_PLUGINS_FOLDERNAME='plugins'
37
- # folder containing plugins in the gem's main folder
38
- GEM_PLUGINS_FOLDER='aspera/cli/plugins'
39
40
  RUBY_FILE_EXT='.rb'
40
41
  AOC_COMMAND_V1='files'
41
42
  AOC_COMMAND_V2='aspera'
@@ -43,36 +44,36 @@ module Aspera
43
44
  AOC_COMMAND_CURRENT=AOC_COMMAND_V3
44
45
  CONNECT_WEB_URL = 'https://d3gcli72yxqn2z.cloudfront.net/connect'
45
46
  CONNECT_VERSIONS = 'connectversions.js'
47
+ TRANSFER_SDK_ARCHIVE_URL = 'https://ibm.biz/aspera_sdk'
46
48
  DEMO='demo'
49
+ DEMO_SERVER_PRESET='demoserver'
50
+ AOC_PATH_API_CLIENTS='admin/api-clients'
47
51
  def option_preset; nil; end
48
52
 
49
53
  def option_preset=(value)
50
54
  self.options.add_option_preset(preset_by_name(value))
51
55
  end
52
56
 
53
- private_constant :ASPERA_HOME_FOLDER_NAME,:DEFAULT_CONFIG_FILENAME,:CONF_PRESET_CONFIG,:CONF_PRESET_VERSION,:CONF_PRESET_DEFAULT,:PROGRAM_NAME_V1,:PROGRAM_NAME_V2,:DEFAULT_REDIRECT,:ASPERA_PLUGINS_FOLDERNAME,:GEM_PLUGINS_FOLDER,:RUBY_FILE_EXT,:AOC_COMMAND_V1,:AOC_COMMAND_V2,:AOC_COMMAND_V3,:AOC_COMMAND_CURRENT,:DEMO
54
- attr_accessor :option_ak_secret,:option_secrets
57
+ 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
55
58
 
56
- def initialize(env,tool_name,help_url,version)
59
+ def initialize(env,tool_name,help_url,version,main_folder)
57
60
  super(env)
58
- @option_ak_secret=nil
59
- @option_secrets={}
61
+ raise 'missing secret manager' if @agents[:secret].nil?
60
62
  @plugins={}
61
63
  @plugin_lookup_folders=[]
62
64
  @use_plugin_defaults=true
63
65
  @config_presets=nil
66
+ @connect_versions=nil
64
67
  @program_version=version
65
68
  @tool_name=tool_name
66
69
  @help_url=help_url
67
- @main_folder=File.join(Dir.home,ASPERA_HOME_FOLDER_NAME,tool_name)
70
+ @main_folder=main_folder
68
71
  @conf_file_default=File.join(@main_folder,DEFAULT_CONFIG_FILENAME)
69
72
  @option_config_file=@conf_file_default
70
- @connect_versions=nil
71
- # set folder where generated FASP files are
72
- Fasp::Installation.instance.folder=File.join(@main_folder,'sdk')
73
- FileUtils.mkdir_p(Fasp::Installation.instance.folder)
73
+ Log.log.debug("#{tool_name} folder: #{@main_folder}")
74
+ # set folder for FASP SDK
74
75
  add_plugin_lookup_folder(File.join(@main_folder,ASPERA_PLUGINS_FOLDERNAME))
75
- add_plugin_lookup_folder(File.join(Main.gem_root,GEM_PLUGINS_FOLDER))
76
+ add_plugin_lookup_folder(self.class.gem_plugins_folder)
76
77
  # do file parameter first
77
78
  self.options.set_obj_attr(:config_file,self,:option_config_file)
78
79
  self.options.add_opt_simple(:config_file,"read parameters from file in YAML format, current=#{@option_config_file}")
@@ -86,35 +87,74 @@ module Aspera
86
87
  self.options.set_obj_attr(:ascp_path,self,:option_ascp_path)
87
88
  self.options.set_obj_attr(:use_product,self,:option_use_product)
88
89
  self.options.set_obj_attr(:preset,self,:option_preset)
89
- self.options.set_obj_attr(:secret,self,:option_ak_secret)
90
- self.options.set_obj_attr(:secrets,self,:option_secrets)
91
- self.options.add_opt_boolean(:override,"override existing value")
92
- self.options.add_opt_switch(:no_default,"-N","do not load default configuration for plugin") { @use_plugin_defaults=false }
90
+ self.options.set_obj_attr(:secret,@agents[:secret],:default_secret)
91
+ self.options.set_obj_attr(:secrets,@agents[:secret],:all_secrets)
92
+ self.options.add_opt_boolean(:override,'override existing value')
93
+ self.options.add_opt_switch(:no_default,'-N','do not load default configuration for plugin') { @use_plugin_defaults=false }
93
94
  self.options.add_opt_boolean(:use_generic_client,'wizard: AoC: use global or org specific jwt client id')
94
- self.options.add_opt_simple(:pkeypath,"path to private key for JWT (wizard)")
95
- self.options.add_opt_simple(:ascp_path,"path to ascp")
96
- self.options.add_opt_simple(:use_product,"use ascp from specified product")
97
- self.options.add_opt_simple(:smtp,"smtp configuration (extended value: hash)")
98
- self.options.add_opt_simple(:fpac,"proxy auto configuration URL")
99
- self.options.add_opt_simple(:preset,"-PVALUE","load the named option preset from current config file")
100
- self.options.add_opt_simple(:default,"set as default configuration for specified plugin")
101
- self.options.add_opt_simple(:secret,"access key secret for node")
102
- self.options.add_opt_simple(:secrets,"access key secret for node")
103
- self.options.add_opt_boolean(:test_mode,"skip user validation in wizard mode")
95
+ self.options.add_opt_simple(:pkeypath,'path to private key for JWT (wizard)')
96
+ self.options.add_opt_simple(:ascp_path,'path to ascp')
97
+ self.options.add_opt_simple(:use_product,'use ascp from specified product')
98
+ self.options.add_opt_simple(:smtp,'smtp configuration (extended value: hash)')
99
+ self.options.add_opt_simple(:fpac,'proxy auto configuration URL')
100
+ self.options.add_opt_simple(:preset,'-PVALUE','load the named option preset from current config file')
101
+ self.options.add_opt_simple(:default,'set as default configuration for specified plugin')
102
+ self.options.add_opt_simple(:secret,'default secret')
103
+ self.options.add_opt_simple(:secrets,'secret repository (Hash)')
104
+ self.options.add_opt_simple(:sdk_url,'URL to get SDK')
105
+ self.options.add_opt_simple(:sdk_folder,'SDK folder location')
106
+ self.options.add_opt_boolean(:test_mode,'skip user validation in wizard mode')
107
+ self.options.add_opt_simple(:version_check_days,Integer,'period to check neew version in days (zero to disable)')
104
108
  self.options.set_option(:use_generic_client,true)
105
109
  self.options.set_option(:test_mode,false)
110
+ self.options.set_option(:version_check_days,7)
111
+ self.options.set_option(:sdk_url,TRANSFER_SDK_ARCHIVE_URL)
112
+ self.options.set_option(:sdk_folder,File.join(@main_folder,'sdk'))
106
113
  self.options.parse_options!
107
- raise CliBadArgument,"secrets shall be Hash" unless @option_secrets.is_a?(Hash)
114
+ raise CliBadArgument,'secrets shall be Hash' unless @agents[:secret].all_secrets.is_a?(Hash)
115
+ Fasp::Installation.instance.folder=self.options.get_option(:sdk_folder,:mandatory)
108
116
  end
109
117
 
110
- def get_secret(id=nil,mandatory=true)
111
- secret=self.options.get_option(:secret,:optional) || @option_secrets[id]
112
- raise "please provide secret for #{id}" if secret.nil? and mandatory
113
- return secret
118
+ def check_gem_version
119
+ this_gem_name=File.basename(File.dirname(self.class.gem_root)).gsub(/-[0-9].*$/,'')
120
+ latest_version=begin
121
+ Rest.new(base_url: 'https://rubygems.org/api/v1').read("versions/#{this_gem_name}/latest.json")[:data]['version']
122
+ rescue
123
+ Log.log.warn('Could not retrieve latest gem version on rubygems.')
124
+ '0'
125
+ end
126
+ 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)}
114
127
  end
115
128
 
116
- def get_secrets
117
- return @option_secrets
129
+ def periodic_check_newer_gem_version
130
+ # get verification period
131
+ delay_days=options.get_option(:version_check_days,:mandatory)
132
+ Log.log.info("check days: #{delay_days}")
133
+ # check only if not zero day
134
+ if !delay_days.eql?(0)
135
+ # get last date from persistency
136
+ last_check_array=[]
137
+ check_date_persist=PersistencyActionOnce.new(
138
+ manager: persistency,
139
+ data: last_check_array,
140
+ ids: ['version_last_check'])
141
+ # get persisted date or nil
142
+ last_check_date = begin
143
+ Date.strptime(last_check_array.first, '%Y/%m/%d')
144
+ rescue
145
+ nil
146
+ end
147
+ current_date=Date.today
148
+ Log.log.debug("days elapsed: #{last_check_date.is_a?(Date) ? current_date - last_check_date : last_check_date.class.name}")
149
+ if last_check_date.nil? or (current_date - last_check_date) > delay_days
150
+ last_check_array[0]=current_date.strftime('%Y/%m/%d')
151
+ check_date_persist.save
152
+ check_data=check_gem_version
153
+ if check_data[:need_update]
154
+ Log.log.warn("A new version is available: #{check_data[:latest]}. You have #{check_data[:current]}. Upgrade with: gem update #{check_data[:name]}")
155
+ end
156
+ end
157
+ end
118
158
  end
119
159
 
120
160
  # retrieve structure from cloud (CDN) with all versions available
@@ -150,15 +190,33 @@ module Aspera
150
190
  require 'openssl'
151
191
  priv_key = OpenSSL::PKey::RSA.new(4096)
152
192
  File.write(private_key_path,priv_key.to_s)
153
- File.write(private_key_path+".pub",priv_key.public_key.to_s)
193
+ File.write(private_key_path+'.pub',priv_key.public_key.to_s)
154
194
  nil
155
195
  end
156
196
 
197
+ # folder containing plugins in the gem's main folder
198
+ def self.gem_plugins_folder
199
+ File.dirname(File.expand_path(__FILE__))
200
+ end
201
+
202
+ # find the root folder of gem where this class is
203
+ # go up as many times as englobing modules (not counting class, as it is a file)
204
+ def self.gem_root
205
+ File.expand_path(Module.nesting[1].to_s.gsub('::','/').gsub(%r([^/]+),'..'),File.dirname(__FILE__))
206
+ end
207
+
208
+ # instanciate a plugin
209
+ # plugins must be Capitalized
210
+ def self.plugin_new(plugin_name_sym,env)
211
+ # Module.nesting[2] is Aspera::Cli
212
+ return Object::const_get("#{Module.nesting[2].to_s}::Plugins::#{plugin_name_sym.to_s.capitalize}").new(env)
213
+ end
214
+
157
215
  def self.flatten_all_config(t)
158
216
  r=[]
159
217
  t.each do |k,v|
160
218
  v.each do |kk,vv|
161
- r.push({"config"=>k,"parameter"=>kk,"value"=>vv})
219
+ r.push({'config'=>k,'parameter'=>kk,'value'=>vv})
162
220
  end
163
221
  end
164
222
  return r
@@ -168,12 +226,12 @@ module Aspera
168
226
  # creates one if none already created
169
227
  # @return preset that contains global default
170
228
  def set_global_default(key,value)
171
- global_default_preset_name=get_plugin_default_config_name(CONF_GLOBAL_SYM)
172
- if global_default_preset_name.nil?
173
- global_default_preset_name='global_common_defaults'
174
- @config_presets[global_default_preset_name]={}
175
- end
229
+ # get default preset if it exists
230
+ global_default_preset_name=get_plugin_default_config_name(CONF_GLOBAL_SYM) || CONF_PRESET_GLOBAL
231
+ @config_presets[global_default_preset_name]||={}
176
232
  @config_presets[global_default_preset_name][key.to_s]=value
233
+ self.format.display_status("Updated: #{global_default_preset_name}: #{key} <- #{value}")
234
+ save_presets_to_config_file
177
235
  return global_default_preset_name
178
236
  end
179
237
 
@@ -192,7 +250,7 @@ module Aspera
192
250
  # @return the hash from name (also expands possible includes)
193
251
  def preset_by_name(config_name, include_path=[])
194
252
  raise CliError,"no such config preset: #{config_name}" unless @config_presets.has_key?(config_name)
195
- raise CliError,"loop in include" if include_path.include?(config_name)
253
+ raise CliError,'loop in include' if include_path.include?(config_name)
196
254
  return expanded_with_preset_includes(@config_presets[config_name],include_path.clone.push(config_name))
197
255
  end
198
256
 
@@ -219,7 +277,7 @@ module Aspera
219
277
  end
220
278
 
221
279
  def option_ascp_path
222
- Fasp::Installation.instance.ascp_path
280
+ Fasp::Installation.instance.path(:ascp)
223
281
  end
224
282
 
225
283
  def option_use_product=(value)
@@ -227,7 +285,7 @@ module Aspera
227
285
  end
228
286
 
229
287
  def option_use_product
230
- "write-only value"
288
+ 'write-only value'
231
289
  end
232
290
 
233
291
  def convert_preset_path(old_name,new_name,files_to_copy)
@@ -271,22 +329,21 @@ module Aspera
271
329
  # if no file found, create default config
272
330
  if conf_file_to_load.nil?
273
331
  Log.log.warn("No config file found. Creating empty configuration file: #{@option_config_file}")
274
- @config_presets={CONF_PRESET_CONFIG=>{CONF_PRESET_VERSION=>@program_version},CONF_PRESET_DEFAULT=>{'server'=>'demoserver'},
275
- 'demoserver'=>{'url'=>'ssh://'+DEMO+'.asperasoft.com:33001','username'=>AOC_COMMAND_V2,'ssAP'.downcase.reverse+'drow'.reverse=>DEMO+AOC_COMMAND_V2}}
332
+ @config_presets={CONF_PRESET_CONFIG=>{CONF_PRESET_VERSION=>@program_version}}
276
333
  else
277
334
  Log.log.debug "loading #{@option_config_file}"
278
335
  @config_presets=YAML.load_file(conf_file_to_load)
279
336
  end
280
337
  files_to_copy=[]
281
338
  Log.log.debug "Available_presets: #{@config_presets}"
282
- raise "Expecting YAML Hash" unless @config_presets.is_a?(Hash)
339
+ raise 'Expecting YAML Hash' unless @config_presets.is_a?(Hash)
283
340
  # check there is at least the config section
284
341
  if !@config_presets.has_key?(CONF_PRESET_CONFIG)
285
342
  raise "Cannot find key: #{CONF_PRESET_CONFIG}"
286
343
  end
287
344
  version=@config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]
288
345
  if version.nil?
289
- raise "No version found in config section."
346
+ raise 'No version found in config section.'
290
347
  end
291
348
  # oldest compatible conf file format, update to latest version when an incompatible change is made
292
349
  # check compatibility of version of conf file
@@ -315,24 +372,24 @@ module Aspera
315
372
  end
316
373
  # Place new compatibility code here
317
374
  if save_required
318
- Log.log.warn("Saving automatic conversion.")
375
+ Log.log.warn('Saving automatic conversion.')
319
376
  @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]=@program_version
320
377
  save_presets_to_config_file
321
- Log.log.warn("Copying referenced files")
378
+ Log.log.warn('Copying referenced files')
322
379
  files_to_copy.each do |file|
323
380
  FileUtils.cp(file,@main_folder)
324
381
  Log.log.warn("..#{file} -> #{@main_folder}")
325
382
  end
326
383
  end
327
384
  rescue Psych::SyntaxError => e
328
- Log.log.error("YAML error in config file")
385
+ Log.log.error('YAML error in config file')
329
386
  raise e
330
387
  rescue => e
331
388
  Log.log.debug("-> #{e}")
332
389
  new_name="#{@option_config_file}.pre#{@program_version}.manual_conversion_needed"
333
390
  File.rename(@option_config_file,new_name)
334
391
  Log.log.warn("Renamed config file to #{new_name}.")
335
- Log.log.warn("Manual Conversion is required. Next time, a new empty file will be created.")
392
+ Log.log.warn('Manual Conversion is required. Next time, a new empty file will be created.')
336
393
  raise CliError,e.to_s
337
394
  end
338
395
  end
@@ -397,10 +454,10 @@ module Aspera
397
454
  fileurl = one_link['href']
398
455
  filename=fileurl.gsub(%r{.*/},'')
399
456
  api_connect_cdn.call({:operation=>'GET',:subpath=>fileurl,:save_to_file=>File.join(folder_dest,filename)})
400
- return Main.result_status("downloaded: #{filename}")
457
+ return Main.result_status("Downloaded: #{filename}")
401
458
  when :open #
402
459
  OpenApplication.instance.uri(one_link['href'])
403
- return Main.result_status("opened: #{one_link['href']}")
460
+ return Main.result_status("Opened: #{one_link['href']}")
404
461
  end
405
462
  end
406
463
  end
@@ -413,24 +470,24 @@ module Aspera
413
470
  when :connect
414
471
  return execute_connect_action
415
472
  when :use
416
- default_ascp=self.options.get_next_argument('path to ascp')
417
- raise "file name must be ascp" unless File.basename(default_ascp).eql?('ascp')
418
- raise "no such file: #{default_ascp}" unless File.exist?(default_ascp)
419
- raise "not executable: #{default_ascp}" unless File.executable?(default_ascp)
420
- preset_name=set_global_default(:ascp_path,default_ascp)
421
- save_presets_to_config_file
422
- return {:type=>:status, :data=>"saved to default global preset #{preset_name}"}
473
+ ascp_path=self.options.get_next_argument('path to ascp')
474
+ ascp_version=Fasp::Installation.instance.get_ascp_version(ascp_path)
475
+ self.format.display_status("ascp version: #{ascp_version}")
476
+ preset_name=set_global_default(:ascp_path,ascp_path)
477
+ return Main.result_status("Saved to default global preset #{preset_name}")
423
478
  when :show # shows files used
424
479
  return {:type=>:status, :data=>Fasp::Installation.instance.path(:ascp)}
425
480
  when :info # shows files used
426
481
  data=Fasp::Installation::FILES.inject({}) do |m,v|
427
- m[v.to_s]=Fasp::Installation.instance.path(v) rescue "Not Found"
482
+ m[v.to_s]=Fasp::Installation.instance.path(v) rescue 'Not Found'
428
483
  m
429
484
  end
430
485
  # read PATHs from ascp directly, and pvcl modules as well
431
486
  Open3.popen3(Fasp::Installation.instance.path(:ascp),'-DDL-') do |stdin, stdout, stderr, thread|
487
+ last_line=''
432
488
  while line=stderr.gets do
433
489
  line.chomp!
490
+ last_line=line
434
491
  case line
435
492
  when %r{^DBG Path ([^ ]+) (dir|file) +: (.*)$};data[$1]=$3
436
493
  when %r{^DBG Added module group:"([^"]+)" name:"([^"]+)", version:"([^"]+)" interface:"([^"]+)"$};data[$2]=$4
@@ -439,6 +496,9 @@ module Aspera
439
496
  when %r{^LOG Initializing FASP version ([^,]+),};data['ascp_version']=$1
440
497
  end
441
498
  end
499
+ if !thread.value.exitstatus.eql?(1) and !data.has_key?('root')
500
+ raise last_line
501
+ end
442
502
  end
443
503
  data['keypass']=Fasp::Installation.instance.bypass_pass
444
504
  return {:type=>:single_object, :data=>data}
@@ -450,18 +510,17 @@ module Aspera
450
510
  when :use
451
511
  default_product=self.options.get_next_argument('product name')
452
512
  Fasp::Installation.instance.use_ascp_from_product(default_product)
453
- preset_name=set_global_default(:ascp_path,Fasp::Installation.instance.ascp_path)
454
- save_presets_to_config_file
455
- return {:type=>:status, :data=>"saved to default global preset #{preset_name}"}
513
+ preset_name=set_global_default(:ascp_path,Fasp::Installation.instance.path(:ascp))
514
+ return Main.result_status("Saved to default global preset #{preset_name}")
456
515
  end
457
516
  when :install
458
- v=Fasp::Installation.instance.install_sdk
459
- return {:type=>:status, :data=>"Installed version #{v}"}
517
+ v=Fasp::Installation.instance.install_sdk(self.options.get_option(:sdk_url,:mandatory))
518
+ return Main.result_status("Installed version #{v}")
460
519
  end
461
520
  raise "unexpected case: #{command}"
462
521
  end
463
522
 
464
- 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]
523
+ 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]
465
524
 
466
525
  # "config" plugin
467
526
  def execute_action
@@ -480,7 +539,7 @@ module Aspera
480
539
  when :delete
481
540
  @config_presets.delete(config_name)
482
541
  save_presets_to_config_file
483
- return Main.result_status("deleted: #{config_name}")
542
+ return Main.result_status("Deleted: #{config_name}")
484
543
  when :get
485
544
  param_name=self.options.get_next_argument('parameter name')
486
545
  value=selected_preset[param_name]
@@ -493,7 +552,7 @@ module Aspera
493
552
  param_name=self.options.get_next_argument('parameter name')
494
553
  selected_preset.delete(param_name)
495
554
  save_presets_to_config_file
496
- return Main.result_status("removed: #{config_name}: #{param_name}")
555
+ return Main.result_status("Removed: #{config_name}: #{param_name}")
497
556
  when :set
498
557
  param_name=self.options.get_next_argument('parameter name')
499
558
  param_value=self.options.get_next_argument('parameter value')
@@ -506,7 +565,7 @@ module Aspera
506
565
  end
507
566
  selected_preset[param_name]=param_value
508
567
  save_presets_to_config_file
509
- return Main.result_status("updated: #{config_name}: #{param_name} <- #{param_value}")
568
+ return Main.result_status("Updated: #{config_name}: #{param_name} <- #{param_value}")
510
569
  when :initialize
511
570
  config_value=self.options.get_next_argument('extended value (Hash)')
512
571
  if @config_presets.has_key?(config_name)
@@ -514,7 +573,7 @@ module Aspera
514
573
  end
515
574
  @config_presets[config_name]=config_value
516
575
  save_presets_to_config_file
517
- return Main.result_status("modified: #{@option_config_file}")
576
+ return Main.result_status("Modified: #{@option_config_file}")
518
577
  when :update
519
578
  default_for_plugin=self.options.get_option(:default,:optional)
520
579
  # get unprocessed options
@@ -527,7 +586,7 @@ module Aspera
527
586
  @config_presets[CONF_PRESET_DEFAULT][default_for_plugin]=config_name
528
587
  end
529
588
  save_presets_to_config_file
530
- return Main.result_status("updated: #{config_name}")
589
+ return Main.result_status("Updated: #{config_name}")
531
590
  when :ask
532
591
  self.options.ask_missing_mandatory=:yes
533
592
  @config_presets[config_name]||={}
@@ -536,10 +595,12 @@ module Aspera
536
595
  @config_presets[config_name][optionname]=option_value
537
596
  end
538
597
  save_presets_to_config_file
539
- return Main.result_status("updated: #{config_name}")
598
+ return Main.result_status("Updated: #{config_name}")
540
599
  end
541
600
  when :documentation
542
- OpenApplication.instance.uri(@help_url)
601
+ section=options.get_next_argument('private key file path',:single,:optional)
602
+ section='#'+section unless section.nil?
603
+ OpenApplication.instance.uri("#{@help_url}#{section}")
543
604
  return Main.result_nothing
544
605
  when :open
545
606
  OpenApplication.instance.uri("#{@option_config_file}") #file://
@@ -547,9 +608,9 @@ module Aspera
547
608
  when :genkey # generate new rsa key
548
609
  private_key_path=self.options.get_next_argument('private key file path')
549
610
  generate_new_key(private_key_path)
550
- return Main.result_status('generated key: '+private_key_path)
611
+ return Main.result_status('Generated key: '+private_key_path)
551
612
  when :echo # display the content of a value given on command line
552
- result={:type=>:other_struct, :data=>self.options.get_next_argument("value")}
613
+ result={:type=>:other_struct, :data=>self.options.get_next_argument('value')}
553
614
  # special for csv
554
615
  result[:type]=:object_list if result[:data].is_a?(Array) and result[:data].first.is_a?(Hash)
555
616
  return result
@@ -564,28 +625,27 @@ module Aspera
564
625
  return {:type=>:object_list,:data=>self.class.flatten_all_config(@config_presets)}
565
626
  when :wizard
566
627
  self.options.ask_missing_mandatory=true
567
- #self.options.set_option(:interactive,:yes)
568
628
  # register url option
569
629
  BasicAuthPlugin.new(@agents.merge(skip_option_header: true))
570
630
  instance_url=self.options.get_option(:url,:mandatory)
571
631
  appli=ApiDetector.discover_product(instance_url)
572
632
  case appli[:product]
573
633
  when :aoc
574
- self.format.display_status("Detected: Aspera on Cloud".bold)
634
+ self.format.display_status('Detected: Aspera on Cloud'.bold)
575
635
  organization,instance_domain=AoC.parse_url(instance_url)
576
636
  aspera_preset_name='aoc_'+organization
577
637
  self.format.display_status("Preparing preset: #{aspera_preset_name}")
578
638
  # init defaults if necessary
579
639
  @config_presets[CONF_PRESET_DEFAULT]||=Hash.new
580
640
  if !option_override
581
- raise CliError,"a default configuration already exists for plugin '#{AOC_COMMAND_V2}' (use --override=yes)" if @config_presets[CONF_PRESET_DEFAULT].has_key?(AOC_COMMAND_V2)
641
+ raise CliError,"a default configuration already exists for plugin '#{AOC_COMMAND_CURRENT}' (use --override=yes)" if @config_presets[CONF_PRESET_DEFAULT].has_key?(AOC_COMMAND_CURRENT)
582
642
  raise CliError,"preset already exists: #{aspera_preset_name} (use --override=yes)" if @config_presets.has_key?(aspera_preset_name)
583
643
  end
584
644
  # lets see if path to priv key is provided
585
645
  private_key_path=self.options.get_option(:pkeypath,:optional)
586
646
  # give a chance to provide
587
647
  if private_key_path.nil?
588
- self.format.display_status("Please provide path to your private RSA key, or empty to generate one:")
648
+ self.format.display_status('Please provide path to your private RSA key, or empty to generate one:')
589
649
  private_key_path=self.options.get_option(:pkeypath,:mandatory).to_s
590
650
  end
591
651
  # else generate path
@@ -593,69 +653,69 @@ module Aspera
593
653
  private_key_path=File.join(@main_folder,'aspera_aoc_key')
594
654
  end
595
655
  if File.exist?(private_key_path)
596
- self.format.display_status("Using existing key:")
656
+ self.format.display_status('Using existing key:')
597
657
  else
598
- self.format.display_status("Generating key...")
658
+ self.format.display_status('Generating key...')
599
659
  generate_new_key(private_key_path)
600
- self.format.display_status("Created:")
660
+ self.format.display_status('Created:')
601
661
  end
602
662
  self.format.display_status("#{private_key_path}")
603
663
  pub_key_pem=OpenSSL::PKey::RSA.new(File.read(private_key_path)).public_key.to_s
604
- # define options
664
+ # declare command line options for AoC
605
665
  require 'aspera/cli/plugins/aoc'
606
666
  # make username mandatory for jwt, this triggers interactive input
607
667
  self.options.get_option(:username,:mandatory)
608
- files_plugin=Plugins::Oncloud.new(@agents.merge({skip_basic_auth_options: true, private_key_path: private_key_path}))
668
+ # instanciate AoC plugin, so that command line options are known
669
+ files_plugin=self.class.plugin_new(AOC_COMMAND_CURRENT,@agents.merge({skip_basic_auth_options: true, private_key_path: private_key_path}))
670
+ aoc_api=files_plugin.get_api
609
671
  auto_set_pub_key=false
610
672
  auto_set_jwt=false
611
673
  use_browser_authentication=false
612
-
613
674
  if self.options.get_option(:use_generic_client)
614
- self.format.display_status("Using global client_id.")
615
- self.format.display_status("Please Login to your Aspera on Cloud instance.".red)
616
- self.format.display_status("Navigate to your \"Account Settings\"".red)
617
- self.format.display_status("Check or update the value of \"Public Key\" to be:".red.blink)
675
+ self.format.display_status('Using global client_id.')
676
+ self.format.display_status('Please Login to your Aspera on Cloud instance.'.red)
677
+ self.format.display_status('Navigate to your "Account Settings"'.red)
678
+ self.format.display_status('Check or update the value of "Public Key" to be:'.red.blink)
618
679
  self.format.display_status("#{pub_key_pem}")
619
680
  if ! self.options.get_option(:test_mode)
620
- self.format.display_status("Once updated or validated, press enter.")
681
+ self.format.display_status('Once updated or validated, press enter.')
621
682
  OpenApplication.instance.uri(instance_url)
622
683
  STDIN.gets
623
684
  end
624
685
  else
625
- self.format.display_status("Using organization specific client_id.")
686
+ self.format.display_status('Using organization specific client_id.')
626
687
  if self.options.get_option(:client_id,:optional).nil? or self.options.get_option(:client_secret,:optional).nil?
627
- self.format.display_status("Please login to your Aspera on Cloud instance.".red)
628
- self.format.display_status("Go to: Apps->Admin->Organization->Integrations")
629
- self.format.display_status("Create or check if there is an existing integration named:")
688
+ self.format.display_status('Please login to your Aspera on Cloud instance.'.red)
689
+ self.format.display_status('Go to: Apps->Admin->Organization->Integrations')
690
+ self.format.display_status('Create or check if there is an existing integration named:')
630
691
  self.format.display_status("- name: #{@tool_name}")
631
692
  self.format.display_status("- redirect uri: #{DEFAULT_REDIRECT}")
632
- self.format.display_status("- origin: localhost")
633
- self.format.display_status("Once created or identified,")
634
- self.format.display_status("Please enter:".red)
693
+ self.format.display_status('- origin: localhost')
694
+ self.format.display_status('Once created or identified,')
695
+ self.format.display_status('Please enter:'.red)
635
696
  end
636
- OpenApplication.instance.uri(instance_url+"/admin/org/integrations")
697
+ OpenApplication.instance.uri("#{instance_url}/#{AOC_PATH_API_CLIENTS}")
637
698
  self.options.get_option(:client_id,:mandatory)
638
699
  self.options.get_option(:client_secret,:mandatory)
639
700
  use_browser_authentication=true
640
701
  end
641
702
  if use_browser_authentication
642
- self.format.display_status("We will use web authentication to bootstrap.")
643
- self.options.set_option(:auth,:web)
644
- self.options.set_option(:redirect_uri,DEFAULT_REDIRECT)
703
+ self.format.display_status('We will use web authentication to bootstrap.')
645
704
  auto_set_pub_key=true
646
705
  auto_set_jwt=true
647
- self.options.set_option(:scope,AoC::SCOPE_FILES_ADMIN)
706
+ @api_aoc.oauth.params[:auth]=:web
707
+ @api_aoc.oauth.params[:redirect_uri]=DEFAULT_REDIRECT
708
+ @api_aoc.oauth.params[:scope]=AoC::SCOPE_FILES_ADMIN
648
709
  end
649
- files_plugin.update_aoc_api
650
- myself=files_plugin.api_aoc.read('self')[:data]
710
+ myself=aoc_api.read('self')[:data]
651
711
  if auto_set_pub_key
652
- raise CliError,"public key is already set in profile (use --override=yes)" unless myself['public_key'].empty? or option_override
653
- self.format.display_status("Updating profile with new key")
654
- files_plugin.api_aoc.update("users/#{myself['id']}",{'public_key'=>pub_key_pem})
712
+ raise CliError,'public key is already set in profile (use --override=yes)' unless myself['public_key'].empty? or option_override
713
+ self.format.display_status('Updating profile with new key')
714
+ aoc_api.update("users/#{myself['id']}",{'public_key'=>pub_key_pem})
655
715
  end
656
716
  if auto_set_jwt
657
- self.format.display_status("Enabling JWT for client")
658
- files_plugin.api_aoc.update("clients/#{self.options.get_option(:client_id)}",{'jwt_grant_enabled'=>true,'explicit_authorization_required'=>false})
717
+ self.format.display_status('Enabling JWT for client')
718
+ aoc_api.update("clients/#{self.options.get_option(:client_id)}",{'jwt_grant_enabled'=>true,'explicit_authorization_required'=>false})
659
719
  end
660
720
  self.format.display_status("creating new config preset: #{aspera_preset_name}")
661
721
  @config_presets[aspera_preset_name]={
@@ -669,20 +729,21 @@ module Aspera
669
729
  o=self.options.get_option(s)
670
730
  @config_presets[s.to_s] = o unless o.nil?
671
731
  end
672
- self.format.display_status("Setting config preset as default for #{AOC_COMMAND_V2}")
673
- @config_presets[CONF_PRESET_DEFAULT][AOC_COMMAND_V2]=aspera_preset_name
674
- self.format.display_status("saving config file")
732
+ self.format.display_status("Setting config preset as default for #{AOC_COMMAND_CURRENT}")
733
+ @config_presets[CONF_PRESET_DEFAULT][AOC_COMMAND_CURRENT]=aspera_preset_name
734
+ self.format.display_status('saving config file')
675
735
  save_presets_to_config_file
676
736
  return Main.result_status("Done.\nYou can test with:\n#{@tool_name} #{AOC_COMMAND_CURRENT} user info show")
677
737
  else
678
738
  raise CliBadArgument,"Supports only: aoc. Detected: #{appli}"
679
739
  end
680
740
  when :export_to_cli
681
- self.format.display_status("Exporting: Aspera on Cloud")
741
+ self.format.display_status('Exporting: Aspera on Cloud')
682
742
  require 'aspera/cli/plugins/aoc'
683
743
  # need url / username
684
744
  add_plugin_default_preset(AOC_COMMAND_V3.to_sym)
685
- files_plugin=Plugins::Oncloud.new(@agents) # TODO: is this line needed ?
745
+ # instanciate AoC plugin
746
+ files_plugin=self.class.plugin_new(AOC_COMMAND_CURRENT,@agents) # TODO: is this line needed ?
686
747
  url=self.options.get_option(:url,:mandatory)
687
748
  cli_conf_file=Fasp::Installation.instance.cli_conf_file
688
749
  data=JSON.parse(File.read(cli_conf_file))
@@ -710,24 +771,24 @@ module Aspera
710
771
  entry.merge!(new_conf)
711
772
  end
712
773
  File.write(cli_conf_file,JSON.pretty_generate(data))
713
- return Main.result_status("updated: #{cli_conf_file}")
774
+ return Main.result_status("Updated: #{cli_conf_file}")
714
775
  when :detect
715
776
  # need url / username
716
777
  BasicAuthPlugin.new(@agents)
717
- return Main.result_status("found: #{ApiDetector.discover_product(self.options.get_option(:url,:mandatory))}")
778
+ return Main.result_status("Found: #{ApiDetector.discover_product(self.options.get_option(:url,:mandatory))}")
718
779
  when :coffee
719
780
  OpenApplication.instance.uri('https://enjoyjava.com/wp-content/uploads/2018/01/How-to-make-strong-coffee.jpg')
720
781
  return Main.result_nothing
721
782
  when :ascp
722
783
  execute_action_ascp
723
784
  when :gem_path
724
- return Main.result_status(Main.gem_root)
785
+ return Main.result_status(self.class.gem_root)
725
786
  when :folder
726
787
  return Main.result_status(@main_folder)
727
788
  when :file
728
789
  return Main.result_status(@option_config_file)
729
790
  when :email_test
730
- dest_email=self.options.get_next_argument("destination email")
791
+ dest_email=self.options.get_next_argument('destination email')
731
792
  send_email({
732
793
  to: dest_email,
733
794
  subject: 'Amelia email test',
@@ -738,9 +799,28 @@ module Aspera
738
799
  return {:type=>:single_object,:data=>email_settings}
739
800
  when :proxy_check
740
801
  pac_url=self.options.get_option(:fpac,:mandatory)
741
- server_url=self.options.get_next_argument("server url")
802
+ server_url=self.options.get_next_argument('server url')
742
803
  return Main.result_status(Aspera::ProxyAutoConfig.new(UriReader.read(pac_url)).get_proxy(server_url))
743
- else raise "error"
804
+ when :check_update
805
+ return {:type=>:single_object, :data=>check_gem_version}
806
+ when :initdemo
807
+ if @config_presets.has_key?(DEMO_SERVER_PRESET)
808
+ Log.log.warn("Demo server preset already present: #{DEMO_SERVER_PRESET}")
809
+ else
810
+ Log.log.info("Creating Demo server preset: #{DEMO_SERVER_PRESET}")
811
+ @config_presets[DEMO_SERVER_PRESET]={'url'=>'ssh://'+DEMO+'.asperasoft.com:33001','username'=>AOC_COMMAND_V2,'ssAP'.downcase.reverse+'drow'.reverse=>DEMO+AOC_COMMAND_V2}
812
+ end
813
+ @config_presets[CONF_PRESET_DEFAULT]||={}
814
+ if @config_presets[CONF_PRESET_DEFAULT].has_key?('server')
815
+ Log.log.warn("server default preset already set to: #{@config_presets[CONF_PRESET_DEFAULT]['server']}")
816
+ Log.log.warn("use #{DEMO_SERVER_PRESET} for demo: -P#{DEMO_SERVER_PRESET}") unless DEMO_SERVER_PRESET.eql?(@config_presets[CONF_PRESET_DEFAULT]['server'])
817
+ else
818
+ @config_presets[CONF_PRESET_DEFAULT]['server']=DEMO_SERVER_PRESET
819
+ Log.log.info("setting server default preset to : #{DEMO_SERVER_PRESET}")
820
+ end
821
+ save_presets_to_config_file
822
+ return Main.result_status("Done")
823
+ else raise 'error'
744
824
  end
745
825
  end
746
826
 
@@ -788,7 +868,7 @@ END_OF_MESSAGE
788
868
  end
789
869
 
790
870
  def save_presets_to_config_file
791
- raise "no configuration loaded" if @config_presets.nil?
871
+ raise 'no configuration loaded' if @config_presets.nil?
792
872
  FileUtils.mkdir_p(@main_folder) unless Dir.exist?(@main_folder)
793
873
  Log.log.debug "writing #{@option_config_file}"
794
874
  File.write(@option_config_file,@config_presets.to_yaml)
@@ -799,7 +879,7 @@ END_OF_MESSAGE
799
879
  def get_plugin_default_config_name(plugin_sym)
800
880
  raise "internal error: config_presets shall be defined" if @config_presets.nil?
801
881
  if !@use_plugin_defaults
802
- Log.log.debug("skip default config")
882
+ Log.log.debug('skip default config')
803
883
  return nil
804
884
  end
805
885
  if @config_presets.has_key?(CONF_PRESET_DEFAULT) and