aspera-cli 4.0.0.pre3 → 4.2.1

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +695 -205
  3. data/bin/dascli +13 -0
  4. data/docs/README.erb.md +615 -157
  5. data/docs/test_env.conf +23 -5
  6. data/docs/transfer_spec.html +1 -1
  7. data/examples/aoc.rb +14 -3
  8. data/examples/faspex4.rb +78 -0
  9. data/lib/aspera/aoc.rb +87 -108
  10. data/lib/aspera/cli/formater.rb +2 -0
  11. data/lib/aspera/cli/main.rb +46 -34
  12. data/lib/aspera/cli/plugin.rb +9 -4
  13. data/lib/aspera/cli/plugins/alee.rb +1 -1
  14. data/lib/aspera/cli/plugins/aoc.rb +207 -182
  15. data/lib/aspera/cli/plugins/ats.rb +2 -2
  16. data/lib/aspera/cli/plugins/config.rb +173 -117
  17. data/lib/aspera/cli/plugins/console.rb +2 -2
  18. data/lib/aspera/cli/plugins/faspex.rb +51 -36
  19. data/lib/aspera/cli/plugins/faspex5.rb +82 -41
  20. data/lib/aspera/cli/plugins/node.rb +3 -3
  21. data/lib/aspera/cli/plugins/preview.rb +35 -25
  22. data/lib/aspera/cli/plugins/server.rb +23 -8
  23. data/lib/aspera/cli/transfer_agent.rb +7 -6
  24. data/lib/aspera/cli/version.rb +1 -1
  25. data/lib/aspera/cos_node.rb +33 -28
  26. data/lib/aspera/environment.rb +2 -2
  27. data/lib/aspera/fasp/connect.rb +28 -21
  28. data/lib/aspera/fasp/http_gw.rb +140 -28
  29. data/lib/aspera/fasp/installation.rb +101 -53
  30. data/lib/aspera/fasp/local.rb +88 -45
  31. data/lib/aspera/fasp/manager.rb +15 -0
  32. data/lib/aspera/fasp/node.rb +4 -4
  33. data/lib/aspera/fasp/parameters.rb +6 -18
  34. data/lib/aspera/fasp/resume_policy.rb +13 -12
  35. data/lib/aspera/log.rb +1 -1
  36. data/lib/aspera/node.rb +61 -1
  37. data/lib/aspera/oauth.rb +49 -46
  38. data/lib/aspera/persistency_folder.rb +9 -4
  39. data/lib/aspera/preview/file_types.rb +53 -21
  40. data/lib/aspera/preview/generator.rb +3 -3
  41. data/lib/aspera/rest.rb +29 -18
  42. data/lib/aspera/secrets.rb +20 -0
  43. data/lib/aspera/temp_file_manager.rb +19 -0
  44. data/lib/aspera/web_auth.rb +105 -0
  45. metadata +42 -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
@@ -41,20 +44,21 @@ module Aspera
41
44
  AOC_COMMAND_CURRENT=AOC_COMMAND_V3
42
45
  CONNECT_WEB_URL = 'https://d3gcli72yxqn2z.cloudfront.net/connect'
43
46
  CONNECT_VERSIONS = 'connectversions.js'
47
+ TRANSFER_SDK_ARCHIVE_URL = 'https://ibm.biz/aspera_sdk'
44
48
  DEMO='demo'
49
+ DEMO_SERVER_PRESET='demoserver'
50
+ AOC_PATH_API_CLIENTS='admin/api-clients'
45
51
  def option_preset; nil; end
46
52
 
47
53
  def option_preset=(value)
48
54
  self.options.add_option_preset(preset_by_name(value))
49
55
  end
50
56
 
51
- 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,:RUBY_FILE_EXT,:AOC_COMMAND_V1,:AOC_COMMAND_V2,:AOC_COMMAND_V3,:AOC_COMMAND_CURRENT,:DEMO
52
- 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
53
58
 
54
- def initialize(env,tool_name,help_url,version)
59
+ def initialize(env,tool_name,help_url,version,main_folder)
55
60
  super(env)
56
- @option_ak_secret=nil
57
- @option_secrets={}
61
+ raise 'missing secret manager' if @agents[:secret].nil?
58
62
  @plugins={}
59
63
  @plugin_lookup_folders=[]
60
64
  @use_plugin_defaults=true
@@ -63,19 +67,11 @@ module Aspera
63
67
  @program_version=version
64
68
  @tool_name=tool_name
65
69
  @help_url=help_url
66
- tool_main_env_var="#{tool_name.upcase}_HOME"
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
70
+ @main_folder=main_folder
74
71
  @conf_file_default=File.join(@main_folder,DEFAULT_CONFIG_FILENAME)
75
72
  @option_config_file=@conf_file_default
76
73
  Log.log.debug("#{tool_name} folder: #{@main_folder}")
77
74
  # set folder for FASP SDK
78
- Fasp::Installation.instance.folder=File.join(@main_folder,'sdk')
79
75
  add_plugin_lookup_folder(File.join(@main_folder,ASPERA_PLUGINS_FOLDERNAME))
80
76
  add_plugin_lookup_folder(self.class.gem_plugins_folder)
81
77
  # do file parameter first
@@ -91,35 +87,74 @@ module Aspera
91
87
  self.options.set_obj_attr(:ascp_path,self,:option_ascp_path)
92
88
  self.options.set_obj_attr(:use_product,self,:option_use_product)
93
89
  self.options.set_obj_attr(:preset,self,:option_preset)
94
- self.options.set_obj_attr(:secret,self,:option_ak_secret)
95
- self.options.set_obj_attr(:secrets,self,:option_secrets)
96
- self.options.add_opt_boolean(:override,"override existing value")
97
- 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 }
98
94
  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,"path to private key for JWT (wizard)")
100
- self.options.add_opt_simple(:ascp_path,"path to ascp")
101
- self.options.add_opt_simple(:use_product,"use ascp from specified product")
102
- self.options.add_opt_simple(:smtp,"smtp configuration (extended value: hash)")
103
- self.options.add_opt_simple(:fpac,"proxy auto configuration URL")
104
- self.options.add_opt_simple(:preset,"-PVALUE","load the named option preset from current config file")
105
- self.options.add_opt_simple(:default,"set as default configuration for specified plugin")
106
- self.options.add_opt_simple(:secret,"access key secret for node")
107
- self.options.add_opt_simple(:secrets,"access key secret for node")
108
- 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)')
109
108
  self.options.set_option(:use_generic_client,true)
110
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'))
111
113
  self.options.parse_options!
112
- 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)
113
116
  end
114
117
 
115
- def get_secret(id=nil,mandatory=true)
116
- secret=self.options.get_option(:secret,:optional) || @option_secrets[id]
117
- raise "please provide secret for #{id}" if secret.nil? and mandatory
118
- 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)}
119
127
  end
120
128
 
121
- def get_secrets
122
- 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
123
158
  end
124
159
 
125
160
  # retrieve structure from cloud (CDN) with all versions available
@@ -155,7 +190,7 @@ module Aspera
155
190
  require 'openssl'
156
191
  priv_key = OpenSSL::PKey::RSA.new(4096)
157
192
  File.write(private_key_path,priv_key.to_s)
158
- 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)
159
194
  nil
160
195
  end
161
196
 
@@ -181,7 +216,7 @@ module Aspera
181
216
  r=[]
182
217
  t.each do |k,v|
183
218
  v.each do |kk,vv|
184
- r.push({"config"=>k,"parameter"=>kk,"value"=>vv})
219
+ r.push({'config'=>k,'parameter'=>kk,'value'=>vv})
185
220
  end
186
221
  end
187
222
  return r
@@ -191,12 +226,12 @@ module Aspera
191
226
  # creates one if none already created
192
227
  # @return preset that contains global default
193
228
  def set_global_default(key,value)
194
- global_default_preset_name=get_plugin_default_config_name(CONF_GLOBAL_SYM)
195
- if global_default_preset_name.nil?
196
- global_default_preset_name='global_common_defaults'
197
- @config_presets[global_default_preset_name]={}
198
- 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]||={}
199
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
200
235
  return global_default_preset_name
201
236
  end
202
237
 
@@ -215,7 +250,7 @@ module Aspera
215
250
  # @return the hash from name (also expands possible includes)
216
251
  def preset_by_name(config_name, include_path=[])
217
252
  raise CliError,"no such config preset: #{config_name}" unless @config_presets.has_key?(config_name)
218
- raise CliError,"loop in include" if include_path.include?(config_name)
253
+ raise CliError,'loop in include' if include_path.include?(config_name)
219
254
  return expanded_with_preset_includes(@config_presets[config_name],include_path.clone.push(config_name))
220
255
  end
221
256
 
@@ -250,7 +285,7 @@ module Aspera
250
285
  end
251
286
 
252
287
  def option_use_product
253
- "write-only value"
288
+ 'write-only value'
254
289
  end
255
290
 
256
291
  def convert_preset_path(old_name,new_name,files_to_copy)
@@ -294,22 +329,21 @@ module Aspera
294
329
  # if no file found, create default config
295
330
  if conf_file_to_load.nil?
296
331
  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},CONF_PRESET_DEFAULT=>{'server'=>'demoserver'},
298
- '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}}
299
333
  else
300
334
  Log.log.debug "loading #{@option_config_file}"
301
335
  @config_presets=YAML.load_file(conf_file_to_load)
302
336
  end
303
337
  files_to_copy=[]
304
338
  Log.log.debug "Available_presets: #{@config_presets}"
305
- raise "Expecting YAML Hash" unless @config_presets.is_a?(Hash)
339
+ raise 'Expecting YAML Hash' unless @config_presets.is_a?(Hash)
306
340
  # check there is at least the config section
307
341
  if !@config_presets.has_key?(CONF_PRESET_CONFIG)
308
342
  raise "Cannot find key: #{CONF_PRESET_CONFIG}"
309
343
  end
310
344
  version=@config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]
311
345
  if version.nil?
312
- raise "No version found in config section."
346
+ raise 'No version found in config section.'
313
347
  end
314
348
  # oldest compatible conf file format, update to latest version when an incompatible change is made
315
349
  # check compatibility of version of conf file
@@ -338,24 +372,24 @@ module Aspera
338
372
  end
339
373
  # Place new compatibility code here
340
374
  if save_required
341
- Log.log.warn("Saving automatic conversion.")
375
+ Log.log.warn('Saving automatic conversion.')
342
376
  @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]=@program_version
343
377
  save_presets_to_config_file
344
- Log.log.warn("Copying referenced files")
378
+ Log.log.warn('Copying referenced files')
345
379
  files_to_copy.each do |file|
346
380
  FileUtils.cp(file,@main_folder)
347
381
  Log.log.warn("..#{file} -> #{@main_folder}")
348
382
  end
349
383
  end
350
384
  rescue Psych::SyntaxError => e
351
- Log.log.error("YAML error in config file")
385
+ Log.log.error('YAML error in config file')
352
386
  raise e
353
387
  rescue => e
354
388
  Log.log.debug("-> #{e}")
355
389
  new_name="#{@option_config_file}.pre#{@program_version}.manual_conversion_needed"
356
390
  File.rename(@option_config_file,new_name)
357
391
  Log.log.warn("Renamed config file to #{new_name}.")
358
- 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.')
359
393
  raise CliError,e.to_s
360
394
  end
361
395
  end
@@ -420,10 +454,10 @@ module Aspera
420
454
  fileurl = one_link['href']
421
455
  filename=fileurl.gsub(%r{.*/},'')
422
456
  api_connect_cdn.call({:operation=>'GET',:subpath=>fileurl,:save_to_file=>File.join(folder_dest,filename)})
423
- return Main.result_status("downloaded: #{filename}")
457
+ return Main.result_status("Downloaded: #{filename}")
424
458
  when :open #
425
459
  OpenApplication.instance.uri(one_link['href'])
426
- return Main.result_status("opened: #{one_link['href']}")
460
+ return Main.result_status("Opened: #{one_link['href']}")
427
461
  end
428
462
  end
429
463
  end
@@ -436,24 +470,24 @@ module Aspera
436
470
  when :connect
437
471
  return execute_connect_action
438
472
  when :use
439
- default_ascp=self.options.get_next_argument('path to ascp')
440
- raise "file name must be ascp" unless File.basename(default_ascp).eql?('ascp')
441
- raise "no such file: #{default_ascp}" unless File.exist?(default_ascp)
442
- raise "not executable: #{default_ascp}" unless File.executable?(default_ascp)
443
- preset_name=set_global_default(:ascp_path,default_ascp)
444
- save_presets_to_config_file
445
- 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}")
446
478
  when :show # shows files used
447
479
  return {:type=>:status, :data=>Fasp::Installation.instance.path(:ascp)}
448
480
  when :info # shows files used
449
481
  data=Fasp::Installation::FILES.inject({}) do |m,v|
450
- 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'
451
483
  m
452
484
  end
453
485
  # read PATHs from ascp directly, and pvcl modules as well
454
486
  Open3.popen3(Fasp::Installation.instance.path(:ascp),'-DDL-') do |stdin, stdout, stderr, thread|
487
+ last_line=''
455
488
  while line=stderr.gets do
456
489
  line.chomp!
490
+ last_line=line
457
491
  case line
458
492
  when %r{^DBG Path ([^ ]+) (dir|file) +: (.*)$};data[$1]=$3
459
493
  when %r{^DBG Added module group:"([^"]+)" name:"([^"]+)", version:"([^"]+)" interface:"([^"]+)"$};data[$2]=$4
@@ -462,6 +496,9 @@ module Aspera
462
496
  when %r{^LOG Initializing FASP version ([^,]+),};data['ascp_version']=$1
463
497
  end
464
498
  end
499
+ if !thread.value.exitstatus.eql?(1) and !data.has_key?('root')
500
+ raise last_line
501
+ end
465
502
  end
466
503
  data['keypass']=Fasp::Installation.instance.bypass_pass
467
504
  return {:type=>:single_object, :data=>data}
@@ -474,17 +511,16 @@ module Aspera
474
511
  default_product=self.options.get_next_argument('product name')
475
512
  Fasp::Installation.instance.use_ascp_from_product(default_product)
476
513
  preset_name=set_global_default(:ascp_path,Fasp::Installation.instance.path(:ascp))
477
- save_presets_to_config_file
478
- return {:type=>:status, :data=>"saved to default global preset #{preset_name}"}
514
+ return Main.result_status("Saved to default global preset #{preset_name}")
479
515
  end
480
516
  when :install
481
- v=Fasp::Installation.instance.install_sdk
482
- 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}")
483
519
  end
484
520
  raise "unexpected case: #{command}"
485
521
  end
486
522
 
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]
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]
488
524
 
489
525
  # "config" plugin
490
526
  def execute_action
@@ -503,7 +539,7 @@ module Aspera
503
539
  when :delete
504
540
  @config_presets.delete(config_name)
505
541
  save_presets_to_config_file
506
- return Main.result_status("deleted: #{config_name}")
542
+ return Main.result_status("Deleted: #{config_name}")
507
543
  when :get
508
544
  param_name=self.options.get_next_argument('parameter name')
509
545
  value=selected_preset[param_name]
@@ -516,7 +552,7 @@ module Aspera
516
552
  param_name=self.options.get_next_argument('parameter name')
517
553
  selected_preset.delete(param_name)
518
554
  save_presets_to_config_file
519
- return Main.result_status("removed: #{config_name}: #{param_name}")
555
+ return Main.result_status("Removed: #{config_name}: #{param_name}")
520
556
  when :set
521
557
  param_name=self.options.get_next_argument('parameter name')
522
558
  param_value=self.options.get_next_argument('parameter value')
@@ -529,7 +565,7 @@ module Aspera
529
565
  end
530
566
  selected_preset[param_name]=param_value
531
567
  save_presets_to_config_file
532
- return Main.result_status("updated: #{config_name}: #{param_name} <- #{param_value}")
568
+ return Main.result_status("Updated: #{config_name}: #{param_name} <- #{param_value}")
533
569
  when :initialize
534
570
  config_value=self.options.get_next_argument('extended value (Hash)')
535
571
  if @config_presets.has_key?(config_name)
@@ -537,7 +573,7 @@ module Aspera
537
573
  end
538
574
  @config_presets[config_name]=config_value
539
575
  save_presets_to_config_file
540
- return Main.result_status("modified: #{@option_config_file}")
576
+ return Main.result_status("Modified: #{@option_config_file}")
541
577
  when :update
542
578
  default_for_plugin=self.options.get_option(:default,:optional)
543
579
  # get unprocessed options
@@ -550,7 +586,7 @@ module Aspera
550
586
  @config_presets[CONF_PRESET_DEFAULT][default_for_plugin]=config_name
551
587
  end
552
588
  save_presets_to_config_file
553
- return Main.result_status("updated: #{config_name}")
589
+ return Main.result_status("Updated: #{config_name}")
554
590
  when :ask
555
591
  self.options.ask_missing_mandatory=:yes
556
592
  @config_presets[config_name]||={}
@@ -559,10 +595,12 @@ module Aspera
559
595
  @config_presets[config_name][optionname]=option_value
560
596
  end
561
597
  save_presets_to_config_file
562
- return Main.result_status("updated: #{config_name}")
598
+ return Main.result_status("Updated: #{config_name}")
563
599
  end
564
600
  when :documentation
565
- 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}")
566
604
  return Main.result_nothing
567
605
  when :open
568
606
  OpenApplication.instance.uri("#{@option_config_file}") #file://
@@ -570,9 +608,9 @@ module Aspera
570
608
  when :genkey # generate new rsa key
571
609
  private_key_path=self.options.get_next_argument('private key file path')
572
610
  generate_new_key(private_key_path)
573
- return Main.result_status('generated key: '+private_key_path)
611
+ return Main.result_status('Generated key: '+private_key_path)
574
612
  when :echo # display the content of a value given on command line
575
- result={:type=>:other_struct, :data=>self.options.get_next_argument("value")}
613
+ result={:type=>:other_struct, :data=>self.options.get_next_argument('value')}
576
614
  # special for csv
577
615
  result[:type]=:object_list if result[:data].is_a?(Array) and result[:data].first.is_a?(Hash)
578
616
  return result
@@ -587,14 +625,13 @@ module Aspera
587
625
  return {:type=>:object_list,:data=>self.class.flatten_all_config(@config_presets)}
588
626
  when :wizard
589
627
  self.options.ask_missing_mandatory=true
590
- #self.options.set_option(:interactive,:yes)
591
628
  # register url option
592
629
  BasicAuthPlugin.new(@agents.merge(skip_option_header: true))
593
630
  instance_url=self.options.get_option(:url,:mandatory)
594
631
  appli=ApiDetector.discover_product(instance_url)
595
632
  case appli[:product]
596
633
  when :aoc
597
- self.format.display_status("Detected: Aspera on Cloud".bold)
634
+ self.format.display_status('Detected: Aspera on Cloud'.bold)
598
635
  organization,instance_domain=AoC.parse_url(instance_url)
599
636
  aspera_preset_name='aoc_'+organization
600
637
  self.format.display_status("Preparing preset: #{aspera_preset_name}")
@@ -608,7 +645,7 @@ module Aspera
608
645
  private_key_path=self.options.get_option(:pkeypath,:optional)
609
646
  # give a chance to provide
610
647
  if private_key_path.nil?
611
- 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:')
612
649
  private_key_path=self.options.get_option(:pkeypath,:mandatory).to_s
613
650
  end
614
651
  # else generate path
@@ -616,69 +653,69 @@ module Aspera
616
653
  private_key_path=File.join(@main_folder,'aspera_aoc_key')
617
654
  end
618
655
  if File.exist?(private_key_path)
619
- self.format.display_status("Using existing key:")
656
+ self.format.display_status('Using existing key:')
620
657
  else
621
- self.format.display_status("Generating key...")
658
+ self.format.display_status('Generating key...')
622
659
  generate_new_key(private_key_path)
623
- self.format.display_status("Created:")
660
+ self.format.display_status('Created:')
624
661
  end
625
662
  self.format.display_status("#{private_key_path}")
626
663
  pub_key_pem=OpenSSL::PKey::RSA.new(File.read(private_key_path)).public_key.to_s
627
- # define options
664
+ # declare command line options for AoC
628
665
  require 'aspera/cli/plugins/aoc'
629
666
  # make username mandatory for jwt, this triggers interactive input
630
667
  self.options.get_option(:username,:mandatory)
631
- # instanciate AoC plugin
668
+ # instanciate AoC plugin, so that command line options are known
632
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
633
671
  auto_set_pub_key=false
634
672
  auto_set_jwt=false
635
673
  use_browser_authentication=false
636
674
  if self.options.get_option(:use_generic_client)
637
- self.format.display_status("Using global client_id.")
638
- self.format.display_status("Please Login to your Aspera on Cloud instance.".red)
639
- self.format.display_status("Navigate to your \"Account Settings\"".red)
640
- 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)
641
679
  self.format.display_status("#{pub_key_pem}")
642
680
  if ! self.options.get_option(:test_mode)
643
- self.format.display_status("Once updated or validated, press enter.")
681
+ self.format.display_status('Once updated or validated, press enter.')
644
682
  OpenApplication.instance.uri(instance_url)
645
683
  STDIN.gets
646
684
  end
647
685
  else
648
- self.format.display_status("Using organization specific client_id.")
686
+ self.format.display_status('Using organization specific client_id.')
649
687
  if self.options.get_option(:client_id,:optional).nil? or self.options.get_option(:client_secret,:optional).nil?
650
- self.format.display_status("Please login to your Aspera on Cloud instance.".red)
651
- self.format.display_status("Go to: Apps->Admin->Organization->Integrations")
652
- 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:')
653
691
  self.format.display_status("- name: #{@tool_name}")
654
692
  self.format.display_status("- redirect uri: #{DEFAULT_REDIRECT}")
655
- self.format.display_status("- origin: localhost")
656
- self.format.display_status("Once created or identified,")
657
- 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)
658
696
  end
659
- OpenApplication.instance.uri(instance_url+"/admin/org/integrations")
697
+ OpenApplication.instance.uri("#{instance_url}/#{AOC_PATH_API_CLIENTS}")
660
698
  self.options.get_option(:client_id,:mandatory)
661
699
  self.options.get_option(:client_secret,:mandatory)
662
700
  use_browser_authentication=true
663
701
  end
664
702
  if use_browser_authentication
665
- self.format.display_status("We will use web authentication to bootstrap.")
666
- self.options.set_option(:auth,:web)
667
- self.options.set_option(:redirect_uri,DEFAULT_REDIRECT)
703
+ self.format.display_status('We will use web authentication to bootstrap.')
668
704
  auto_set_pub_key=true
669
705
  auto_set_jwt=true
670
- 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
671
709
  end
672
- files_plugin.update_aoc_api
673
- myself=files_plugin.api_aoc.read('self')[:data]
710
+ myself=aoc_api.read('self')[:data]
674
711
  if auto_set_pub_key
675
- raise CliError,"public key is already set in profile (use --override=yes)" unless myself['public_key'].empty? or option_override
676
- self.format.display_status("Updating profile with new key")
677
- 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})
678
715
  end
679
716
  if auto_set_jwt
680
- self.format.display_status("Enabling JWT for client")
681
- 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})
682
719
  end
683
720
  self.format.display_status("creating new config preset: #{aspera_preset_name}")
684
721
  @config_presets[aspera_preset_name]={
@@ -694,14 +731,14 @@ module Aspera
694
731
  end
695
732
  self.format.display_status("Setting config preset as default for #{AOC_COMMAND_CURRENT}")
696
733
  @config_presets[CONF_PRESET_DEFAULT][AOC_COMMAND_CURRENT]=aspera_preset_name
697
- self.format.display_status("saving config file")
734
+ self.format.display_status('saving config file')
698
735
  save_presets_to_config_file
699
736
  return Main.result_status("Done.\nYou can test with:\n#{@tool_name} #{AOC_COMMAND_CURRENT} user info show")
700
737
  else
701
738
  raise CliBadArgument,"Supports only: aoc. Detected: #{appli}"
702
739
  end
703
740
  when :export_to_cli
704
- self.format.display_status("Exporting: Aspera on Cloud")
741
+ self.format.display_status('Exporting: Aspera on Cloud')
705
742
  require 'aspera/cli/plugins/aoc'
706
743
  # need url / username
707
744
  add_plugin_default_preset(AOC_COMMAND_V3.to_sym)
@@ -734,11 +771,11 @@ module Aspera
734
771
  entry.merge!(new_conf)
735
772
  end
736
773
  File.write(cli_conf_file,JSON.pretty_generate(data))
737
- return Main.result_status("updated: #{cli_conf_file}")
774
+ return Main.result_status("Updated: #{cli_conf_file}")
738
775
  when :detect
739
776
  # need url / username
740
777
  BasicAuthPlugin.new(@agents)
741
- 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))}")
742
779
  when :coffee
743
780
  OpenApplication.instance.uri('https://enjoyjava.com/wp-content/uploads/2018/01/How-to-make-strong-coffee.jpg')
744
781
  return Main.result_nothing
@@ -751,7 +788,7 @@ module Aspera
751
788
  when :file
752
789
  return Main.result_status(@option_config_file)
753
790
  when :email_test
754
- dest_email=self.options.get_next_argument("destination email")
791
+ dest_email=self.options.get_next_argument('destination email')
755
792
  send_email({
756
793
  to: dest_email,
757
794
  subject: 'Amelia email test',
@@ -762,9 +799,28 @@ module Aspera
762
799
  return {:type=>:single_object,:data=>email_settings}
763
800
  when :proxy_check
764
801
  pac_url=self.options.get_option(:fpac,:mandatory)
765
- server_url=self.options.get_next_argument("server url")
802
+ server_url=self.options.get_next_argument('server url')
766
803
  return Main.result_status(Aspera::ProxyAutoConfig.new(UriReader.read(pac_url)).get_proxy(server_url))
767
- 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'
768
824
  end
769
825
  end
770
826
 
@@ -812,7 +868,7 @@ END_OF_MESSAGE
812
868
  end
813
869
 
814
870
  def save_presets_to_config_file
815
- raise "no configuration loaded" if @config_presets.nil?
871
+ raise 'no configuration loaded' if @config_presets.nil?
816
872
  FileUtils.mkdir_p(@main_folder) unless Dir.exist?(@main_folder)
817
873
  Log.log.debug "writing #{@option_config_file}"
818
874
  File.write(@option_config_file,@config_presets.to_yaml)
@@ -823,7 +879,7 @@ END_OF_MESSAGE
823
879
  def get_plugin_default_config_name(plugin_sym)
824
880
  raise "internal error: config_presets shall be defined" if @config_presets.nil?
825
881
  if !@use_plugin_defaults
826
- Log.log.debug("skip default config")
882
+ Log.log.debug('skip default config')
827
883
  return nil
828
884
  end
829
885
  if @config_presets.has_key?(CONF_PRESET_DEFAULT) and