aspera-cli 4.2.0 → 4.4.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +749 -353
  3. data/docs/Makefile +4 -4
  4. data/docs/README.erb.md +743 -283
  5. data/docs/doc_tools.rb +58 -0
  6. data/docs/test_env.conf +9 -1
  7. data/examples/aoc.rb +14 -3
  8. data/examples/faspex4.rb +89 -0
  9. data/lib/aspera/aoc.rb +24 -22
  10. data/lib/aspera/cli/main.rb +48 -20
  11. data/lib/aspera/cli/plugin.rb +13 -6
  12. data/lib/aspera/cli/plugins/aoc.rb +117 -78
  13. data/lib/aspera/cli/plugins/config.rb +127 -80
  14. data/lib/aspera/cli/plugins/faspex.rb +112 -63
  15. data/lib/aspera/cli/plugins/faspex5.rb +29 -25
  16. data/lib/aspera/cli/plugins/node.rb +54 -25
  17. data/lib/aspera/cli/plugins/preview.rb +94 -68
  18. data/lib/aspera/cli/plugins/server.rb +16 -5
  19. data/lib/aspera/cli/transfer_agent.rb +92 -72
  20. data/lib/aspera/cli/version.rb +1 -1
  21. data/lib/aspera/command_line_builder.rb +48 -31
  22. data/lib/aspera/cos_node.rb +4 -3
  23. data/lib/aspera/fasp/http_gw.rb +47 -26
  24. data/lib/aspera/fasp/local.rb +31 -24
  25. data/lib/aspera/fasp/manager.rb +3 -0
  26. data/lib/aspera/fasp/node.rb +23 -1
  27. data/lib/aspera/fasp/parameters.rb +72 -89
  28. data/lib/aspera/fasp/parameters.yaml +531 -0
  29. data/lib/aspera/fasp/uri.rb +1 -1
  30. data/lib/aspera/faspex_gw.rb +10 -9
  31. data/lib/aspera/id_generator.rb +22 -0
  32. data/lib/aspera/node.rb +11 -3
  33. data/lib/aspera/oauth.rb +131 -135
  34. data/lib/aspera/persistency_action_once.rb +11 -7
  35. data/lib/aspera/persistency_folder.rb +6 -26
  36. data/lib/aspera/rest.rb +1 -1
  37. data/lib/aspera/sync.rb +40 -35
  38. data/lib/aspera/timer_limiter.rb +22 -0
  39. data/lib/aspera/web_auth.rb +105 -0
  40. metadata +22 -4
  41. data/docs/transfer_spec.html +0 -99
  42. data/lib/aspera/fasp/aoc.rb +0 -24
@@ -1,6 +1,7 @@
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'
@@ -8,11 +9,13 @@ require 'aspera/proxy_auto_config'
8
9
  require 'aspera/uri_reader'
9
10
  require 'aspera/rest'
10
11
  require 'aspera/persistency_action_once'
12
+ require 'aspera/id_generator'
11
13
  require 'xmlsimple'
12
14
  require 'base64'
13
15
  require 'net/smtp'
14
16
  require 'open3'
15
17
  require 'date'
18
+ require 'erb'
16
19
 
17
20
  module Aspera
18
21
  module Cli
@@ -42,20 +45,45 @@ module Aspera
42
45
  AOC_COMMAND_V2='aspera'
43
46
  AOC_COMMAND_V3='aoc'
44
47
  AOC_COMMAND_CURRENT=AOC_COMMAND_V3
48
+ SERVER_COMMAND='server'
45
49
  CONNECT_WEB_URL = 'https://d3gcli72yxqn2z.cloudfront.net/connect'
46
50
  CONNECT_VERSIONS = 'connectversions.js'
47
51
  TRANSFER_SDK_ARCHIVE_URL = 'https://ibm.biz/aspera_sdk'
48
52
  DEMO='demo'
49
53
  DEMO_SERVER_PRESET='demoserver'
50
54
  AOC_PATH_API_CLIENTS='admin/api-clients'
55
+ EMAIL_TEST_TEMPLATE=<<END_OF_TEMPLATE
56
+ From: <%=from_name%> <<%=from_email%>>
57
+ To: <<%=to%>>
58
+ Subject: Amelia email test
59
+
60
+ It worked !
61
+ END_OF_TEMPLATE
62
+ # special extended values
63
+ EXTV_INCLUDE_PRESETS='incps'
64
+ EXTV_PRESET='preset'
65
+ DEFAULT_CHECK_NEW_VERSION_DAYS=7
66
+ DEFAULT_PRIV_KEY_FILENAME='aspera_aoc_key'
67
+ DEFAULT_PRIVKEY_LENGTH=4096
68
+ private_constant :DEFAULT_CONFIG_FILENAME,:CONF_PRESET_CONFIG,:CONF_PRESET_VERSION,:CONF_PRESET_DEFAULT,
69
+ :CONF_PRESET_GLOBAL,:PROGRAM_NAME_V1,:PROGRAM_NAME_V2,:DEFAULT_REDIRECT,:ASPERA_PLUGINS_FOLDERNAME,
70
+ :RUBY_FILE_EXT,:AOC_COMMAND_V1,:AOC_COMMAND_V2,:AOC_COMMAND_V3,:AOC_COMMAND_CURRENT,:DEMO,
71
+ :TRANSFER_SDK_ARCHIVE_URL,:AOC_PATH_API_CLIENTS,:DEMO_SERVER_PRESET,:EMAIL_TEST_TEMPLATE,:EXTV_INCLUDE_PRESETS,
72
+ :EXTV_PRESET,:DEFAULT_CHECK_NEW_VERSION_DAYS,:DEFAULT_PRIV_KEY_FILENAME,:SERVER_COMMAND
51
73
  def option_preset; nil; end
52
74
 
53
75
  def option_preset=(value)
54
- self.options.add_option_preset(preset_by_name(value))
76
+ case value
77
+ when String
78
+ self.options.add_option_preset(preset_by_name(value))
79
+ when Hash
80
+ self.options.add_option_preset(value)
81
+ else
82
+ raise "Preset definition must be a String for name, or Hash for value"
83
+ end
84
+ nil
55
85
  end
56
86
 
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
58
-
59
87
  def initialize(env,tool_name,help_url,version,main_folder)
60
88
  super(env)
61
89
  raise 'missing secret manager' if @agents[:secret].nil?
@@ -83,33 +111,36 @@ module Aspera
83
111
  # add preset handler (needed for smtp)
84
112
  ExtendedValue.instance.set_handler(EXTV_PRESET,:reader,lambda{|v|preset_by_name(v)})
85
113
  ExtendedValue.instance.set_handler(EXTV_INCLUDE_PRESETS,:decoder,lambda{|v|expanded_with_preset_includes(v)})
86
- self.options.set_obj_attr(:override,self,:option_override,:no)
87
114
  self.options.set_obj_attr(:ascp_path,self,:option_ascp_path)
88
115
  self.options.set_obj_attr(:use_product,self,:option_use_product)
89
116
  self.options.set_obj_attr(:preset,self,:option_preset)
90
117
  self.options.set_obj_attr(:secret,@agents[:secret],:default_secret)
91
118
  self.options.set_obj_attr(:secrets,@agents[:secret],:all_secrets)
92
- self.options.add_opt_boolean(:override,'override existing value')
93
119
  self.options.add_opt_switch(:no_default,'-N','do not load default configuration for plugin') { @use_plugin_defaults=false }
94
- self.options.add_opt_boolean(:use_generic_client,'wizard: AoC: use global or org specific jwt client id')
95
- self.options.add_opt_simple(:pkeypath,'path to private key for JWT (wizard)')
120
+ self.options.add_opt_boolean(:override,'Wizard: override existing value')
121
+ self.options.add_opt_boolean(:use_generic_client,'Wizard: AoC: use global or org specific jwt client id')
122
+ self.options.add_opt_boolean(:default,'Wizard: set as default configuration for specified plugin (also: update)')
123
+ self.options.add_opt_boolean(:test_mode,'Wizard: skip private key check step')
124
+ self.options.add_opt_simple(:pkeypath,'Wizard: path to private key for JWT')
96
125
  self.options.add_opt_simple(:ascp_path,'path to ascp')
97
126
  self.options.add_opt_simple(:use_product,'use ascp from specified product')
98
127
  self.options.add_opt_simple(:smtp,'smtp configuration (extended value: hash)')
99
128
  self.options.add_opt_simple(:fpac,'proxy auto configuration URL')
100
129
  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
130
  self.options.add_opt_simple(:secret,'default secret')
103
131
  self.options.add_opt_simple(:secrets,'secret repository (Hash)')
104
132
  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)')
133
+ self.options.add_opt_simple(:sdk_folder,'SDK folder path')
134
+ self.options.add_opt_simple(:notif_to,'email recipient for notification of transfers')
135
+ self.options.add_opt_simple(:notif_template,'email ERB template for notification of transfers')
136
+ self.options.add_opt_simple(:version_check_days,Integer,'period in days to check new version (zero to disable)')
108
137
  self.options.set_option(:use_generic_client,true)
109
138
  self.options.set_option(:test_mode,false)
110
- self.options.set_option(:version_check_days,7)
139
+ self.options.set_option(:default,true)
140
+ self.options.set_option(:version_check_days,DEFAULT_CHECK_NEW_VERSION_DAYS)
111
141
  self.options.set_option(:sdk_url,TRANSFER_SDK_ARCHIVE_URL)
112
142
  self.options.set_option(:sdk_folder,File.join(@main_folder,'sdk'))
143
+ self.options.set_option(:override,:no)
113
144
  self.options.parse_options!
114
145
  raise CliBadArgument,'secrets shall be Hash' unless @agents[:secret].all_secrets.is_a?(Hash)
115
146
  Fasp::Installation.instance.folder=self.options.get_option(:sdk_folder,:mandatory)
@@ -137,7 +168,7 @@ module Aspera
137
168
  check_date_persist=PersistencyActionOnce.new(
138
169
  manager: persistency,
139
170
  data: last_check_array,
140
- ids: ['version_last_check'])
171
+ id: 'version_last_check')
141
172
  # get persisted date or nil
142
173
  last_check_date = begin
143
174
  Date.strptime(last_check_array.first, '%Y/%m/%d')
@@ -186,9 +217,9 @@ module Aspera
186
217
  end
187
218
  private
188
219
 
189
- def generate_new_key(private_key_path)
220
+ def generate_rsa_private_key(private_key_path,length)
190
221
  require 'openssl'
191
- priv_key = OpenSSL::PKey::RSA.new(4096)
222
+ priv_key = OpenSSL::PKey::RSA.new(length)
192
223
  File.write(private_key_path,priv_key.to_s)
193
224
  File.write(private_key_path+'.pub',priv_key.public_key.to_s)
194
225
  nil
@@ -241,12 +272,8 @@ module Aspera
241
272
  attr_reader :main_folder
242
273
  attr_reader :gem_url
243
274
  attr_reader :plugins
244
- attr_accessor :option_override
245
275
  attr_accessor :option_config_file
246
276
 
247
- EXTV_INCLUDE_PRESETS='incps'
248
- EXTV_PRESET='preset'
249
-
250
277
  # @return the hash from name (also expands possible includes)
251
278
  def preset_by_name(config_name, include_path=[])
252
279
  raise CliError,"no such config preset: #{config_name}" unless @config_presets.has_key?(config_name)
@@ -331,11 +358,11 @@ module Aspera
331
358
  Log.log.warn("No config file found. Creating empty configuration file: #{@option_config_file}")
332
359
  @config_presets={CONF_PRESET_CONFIG=>{CONF_PRESET_VERSION=>@program_version}}
333
360
  else
334
- Log.log.debug "loading #{@option_config_file}"
361
+ Log.log.debug("loading #{@option_config_file}")
335
362
  @config_presets=YAML.load_file(conf_file_to_load)
336
363
  end
337
364
  files_to_copy=[]
338
- Log.log.debug "Available_presets: #{@config_presets}"
365
+ Log.log.debug("Available_presets: #{@config_presets}")
339
366
  raise 'Expecting YAML Hash' unless @config_presets.is_a?(Hash)
340
367
  # check there is at least the config section
341
368
  if !@config_presets.has_key?(CONF_PRESET_CONFIG)
@@ -465,7 +492,7 @@ module Aspera
465
492
  end
466
493
 
467
494
  def execute_action_ascp
468
- command=self.options.get_next_command([:connect,:use,:show,:products,:info,:install])
495
+ command=self.options.get_next_command([:connect,:use,:show,:products,:info,:install,:spec])
469
496
  case command
470
497
  when :connect
471
498
  return execute_connect_action
@@ -516,6 +543,8 @@ module Aspera
516
543
  when :install
517
544
  v=Fasp::Installation.instance.install_sdk(self.options.get_option(:sdk_url,:mandatory))
518
545
  return Main.result_status("Installed version #{v}")
546
+ when :spec
547
+ return {type: :object_list, data: Fasp::Parameters.man_table, fields: ['name','type',Fasp::Parameters::SUPPORTED_AGENTS_SHORT.map{|i|i.to_s},'description'].flatten}
519
548
  end
520
549
  raise "unexpected case: #{command}"
521
550
  end
@@ -575,7 +604,7 @@ module Aspera
575
604
  save_presets_to_config_file
576
605
  return Main.result_status("Modified: #{@option_config_file}")
577
606
  when :update
578
- default_for_plugin=self.options.get_option(:default,:optional)
607
+ default_for_plugin=self.options.get_option(:default,:mandatory)
579
608
  # get unprocessed options
580
609
  theopts=self.options.get_options_table
581
610
  Log.log.debug("opts=#{theopts}")
@@ -607,7 +636,7 @@ module Aspera
607
636
  return Main.result_nothing
608
637
  when :genkey # generate new rsa key
609
638
  private_key_path=self.options.get_next_argument('private key file path')
610
- generate_new_key(private_key_path)
639
+ generate_rsa_private_key(private_key_path,DEFAULT_PRIVKEY_LENGTH)
611
640
  return Main.result_status('Generated key: '+private_key_path)
612
641
  when :echo # display the content of a value given on command line
613
642
  result={:type=>:other_struct, :data=>self.options.get_next_argument('value')}
@@ -624,23 +653,32 @@ module Aspera
624
653
  when :overview
625
654
  return {:type=>:object_list,:data=>self.class.flatten_all_config(@config_presets)}
626
655
  when :wizard
656
+ # interactive mode
627
657
  self.options.ask_missing_mandatory=true
628
658
  # register url option
629
659
  BasicAuthPlugin.new(@agents.merge(skip_option_header: true))
660
+ # get from option, or ask
630
661
  instance_url=self.options.get_option(:url,:mandatory)
662
+ # allow user to tell the preset name
663
+ preset_name=self.options.get_option(:id,:optional)
631
664
  appli=ApiDetector.discover_product(instance_url)
665
+ plugin_name="<replace per app>"
666
+ test_args="<replace per app>"
632
667
  case appli[:product]
633
668
  when :aoc
634
669
  self.format.display_status('Detected: Aspera on Cloud'.bold)
670
+ plugin_name=AOC_COMMAND_CURRENT
635
671
  organization,instance_domain=AoC.parse_url(instance_url)
636
- aspera_preset_name='aoc_'+organization
637
- self.format.display_status("Preparing preset: #{aspera_preset_name}")
672
+ # if not defined by user, generate name
673
+ preset_name=[appli[:product],organization].join('_') if preset_name.nil?
674
+ self.format.display_status("Preparing preset: #{preset_name}")
638
675
  # init defaults if necessary
639
- @config_presets[CONF_PRESET_DEFAULT]||=Hash.new
640
- if !option_override
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)
642
- raise CliError,"preset already exists: #{aspera_preset_name} (use --override=yes)" if @config_presets.has_key?(aspera_preset_name)
643
- end
676
+ @config_presets[CONF_PRESET_DEFAULT]||={}
677
+ option_override=self.options.get_option(:override,:mandatory)
678
+ option_default=self.options.get_option(:default,:mandatory)
679
+ Log.log.error("override=#{option_override} -> #{option_override.class}")
680
+ raise CliError,"A default configuration already exists for plugin '#{plugin_name}' (use --override=yes or --default=no)" if !option_override and option_default and @config_presets[CONF_PRESET_DEFAULT].has_key?(plugin_name)
681
+ raise CliError,"Preset already exists: #{preset_name} (use --override=yes or --id=<name>)" if !option_override and @config_presets.has_key?(preset_name)
644
682
  # lets see if path to priv key is provided
645
683
  private_key_path=self.options.get_option(:pkeypath,:optional)
646
684
  # give a chance to provide
@@ -650,23 +688,23 @@ module Aspera
650
688
  end
651
689
  # else generate path
652
690
  if private_key_path.empty?
653
- private_key_path=File.join(@main_folder,'aspera_aoc_key')
691
+ private_key_path=File.join(@main_folder,DEFAULT_PRIV_KEY_FILENAME)
654
692
  end
655
693
  if File.exist?(private_key_path)
656
694
  self.format.display_status('Using existing key:')
657
695
  else
658
- self.format.display_status('Generating key...')
659
- generate_new_key(private_key_path)
696
+ self.format.display_status("Generating #{DEFAULT_PRIVKEY_LENGTH} bit RSA key...")
697
+ generate_rsa_private_key(private_key_path,DEFAULT_PRIVKEY_LENGTH)
660
698
  self.format.display_status('Created:')
661
699
  end
662
- self.format.display_status("#{private_key_path}")
700
+ self.format.display_status(private_key_path)
663
701
  pub_key_pem=OpenSSL::PKey::RSA.new(File.read(private_key_path)).public_key.to_s
664
702
  # declare command line options for AoC
665
703
  require 'aspera/cli/plugins/aoc'
666
704
  # make username mandatory for jwt, this triggers interactive input
667
705
  self.options.get_option(:username,:mandatory)
668
706
  # 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}))
707
+ files_plugin=self.class.plugin_new(plugin_name,@agents.merge({skip_basic_auth_options: true, private_key_path: private_key_path}))
670
708
  aoc_api=files_plugin.get_api
671
709
  auto_set_pub_key=false
672
710
  auto_set_jwt=false
@@ -709,7 +747,7 @@ module Aspera
709
747
  end
710
748
  myself=aoc_api.read('self')[:data]
711
749
  if auto_set_pub_key
712
- raise CliError,'public key is already set in profile (use --override=yes)' unless myself['public_key'].empty? or option_override
750
+ raise CliError,'Public key is already set in profile (use --override=yes)' unless myself['public_key'].empty? or option_override
713
751
  self.format.display_status('Updating profile with new key')
714
752
  aoc_api.update("users/#{myself['id']}",{'public_key'=>pub_key_pem})
715
753
  end
@@ -717,8 +755,8 @@ module Aspera
717
755
  self.format.display_status('Enabling JWT for client')
718
756
  aoc_api.update("clients/#{self.options.get_option(:client_id)}",{'jwt_grant_enabled'=>true,'explicit_authorization_required'=>false})
719
757
  end
720
- self.format.display_status("creating new config preset: #{aspera_preset_name}")
721
- @config_presets[aspera_preset_name]={
758
+ self.format.display_status("Creating new config preset: #{preset_name}")
759
+ @config_presets[preset_name]={
722
760
  :url.to_s =>self.options.get_option(:url),
723
761
  :username.to_s =>myself['email'],
724
762
  :auth.to_s =>:jwt.to_s,
@@ -727,16 +765,21 @@ module Aspera
727
765
  # set only if non nil
728
766
  [:client_id,:client_secret].each do |s|
729
767
  o=self.options.get_option(s)
730
- @config_presets[s.to_s] = o unless o.nil?
768
+ @config_presets[preset_name][s.to_s] = o unless o.nil?
731
769
  end
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')
735
- save_presets_to_config_file
736
- return Main.result_status("Done.\nYou can test with:\n#{@tool_name} #{AOC_COMMAND_CURRENT} user info show")
770
+ test_args="#{plugin_name} user info show"
737
771
  else
738
772
  raise CliBadArgument,"Supports only: aoc. Detected: #{appli}"
773
+ end # product
774
+ if option_default
775
+ self.format.display_status("Setting config preset as default for #{plugin_name}")
776
+ @config_presets[CONF_PRESET_DEFAULT][plugin_name]=preset_name
777
+ else
778
+ test_args="-P#{preset_name} #{test_args}"
739
779
  end
780
+ self.format.display_status('Saving config file.')
781
+ save_presets_to_config_file
782
+ return Main.result_status("Done.\nYou can test with:\n#{@tool_name} #{test_args}")
740
783
  when :export_to_cli
741
784
  self.format.display_status('Exporting: Aspera on Cloud')
742
785
  require 'aspera/cli/plugins/aoc'
@@ -788,12 +831,7 @@ module Aspera
788
831
  when :file
789
832
  return Main.result_status(@option_config_file)
790
833
  when :email_test
791
- dest_email=self.options.get_next_argument('destination email')
792
- send_email({
793
- to: dest_email,
794
- subject: 'Amelia email test',
795
- body: 'It worked !',
796
- })
834
+ send_email_template({},EMAIL_TEST_TEMPLATE)
797
835
  return Main.result_nothing
798
836
  when :smtp_settings
799
837
  return {:type=>:single_object,:data=>email_settings}
@@ -811,22 +849,23 @@ module Aspera
811
849
  @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
850
  end
813
851
  @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'])
852
+ if @config_presets[CONF_PRESET_DEFAULT].has_key?(SERVER_COMMAND)
853
+ Log.log.warn("Server default preset already set to: #{@config_presets[CONF_PRESET_DEFAULT][SERVER_COMMAND]}")
854
+ Log.log.warn("Use #{DEMO_SERVER_PRESET} for demo: -P#{DEMO_SERVER_PRESET}") unless DEMO_SERVER_PRESET.eql?(@config_presets[CONF_PRESET_DEFAULT][SERVER_COMMAND])
817
855
  else
818
- @config_presets[CONF_PRESET_DEFAULT]['server']=DEMO_SERVER_PRESET
819
- Log.log.info("setting server default preset to : #{DEMO_SERVER_PRESET}")
856
+ @config_presets[CONF_PRESET_DEFAULT][SERVER_COMMAND]=DEMO_SERVER_PRESET
857
+ Log.log.info("Setting server default preset to : #{DEMO_SERVER_PRESET}")
820
858
  end
821
859
  save_presets_to_config_file
822
860
  return Main.result_status("Done")
823
- else raise 'error'
861
+ else raise 'INTERNAL ERROR: wrong case'
824
862
  end
825
863
  end
826
864
 
865
+ # @return email server setting with defaults if not defined
827
866
  def email_settings
828
867
  smtp=self.options.get_option(:smtp,:mandatory)
829
- # change string keys into symbols
868
+ # change string keys into symbol keys
830
869
  smtp=smtp.keys.inject({}){|m,v|m[v.to_sym]=smtp[v];m}
831
870
  # defaults
832
871
  smtp[:tls]||=true
@@ -836,41 +875,49 @@ module Aspera
836
875
  smtp[:domain]||=smtp[:from_email].gsub(/^.*@/,'') if smtp.has_key?(:from_email)
837
876
  # check minimum required
838
877
  [:server,:port,:domain].each do |n|
839
- raise "missing smtp parameter: #{n}" unless smtp.has_key?(n)
878
+ raise "Missing smtp parameter: #{n}" unless smtp.has_key?(n)
840
879
  end
841
880
  Log.log.debug("smtp=#{smtp}")
842
881
  return smtp
843
882
  end
844
883
 
845
- def send_email(email={})
846
- opts=email_settings
847
- email[:from_name]||=opts[:from_name]
848
- email[:from_email]||=opts[:from_email]
849
- # check minimum required
850
- [:from_name,:from_email,:to,:subject].each do |n|
851
- raise "missing email parameter: #{n}" unless email.has_key?(n)
884
+ # create a clean binding (ruby variable environment)
885
+ def empty_binding
886
+ Kernel.binding
887
+ end
888
+
889
+ def send_email_template(vars,email_template_default=nil)
890
+ vars[:to]||=options.get_option(:notif_to,:mandatory)
891
+ notif_template=options.get_option(:notif_template,email_template_default.nil? ? :mandatory : :optional) || email_template_default
892
+ mail_conf=email_settings
893
+ vars[:from_name]||=mail_conf[:from_name]
894
+ vars[:from_email]||=mail_conf[:from_email]
895
+ [:from_name,:from_email].each do |n|
896
+ raise "Missing email parameter: #{n}" unless vars.has_key?(n)
897
+ end
898
+ start_options=[mail_conf[:domain]]
899
+ start_options.push(mail_conf[:username],mail_conf[:password],:login) if mail_conf.has_key?(:username) and mail_conf.has_key?(:password)
900
+ # create a binding with only variables defined in vars
901
+ template_binding=empty_binding
902
+ # add variables to binding
903
+ vars.each do |k,v|
904
+ raise "key (#{k.class}) must be Symbol" unless k.is_a?(Symbol)
905
+ template_binding.local_variable_set(k,v)
852
906
  end
853
- msg = <<END_OF_MESSAGE
854
- From: #{email[:from_name]} <#{email[:from_email]}>
855
- To: <#{email[:to]}>
856
- Subject: #{email[:subject]}
857
-
858
- #{email[:body]}
859
- END_OF_MESSAGE
860
- start_options=[opts[:domain]]
861
- start_options.push(opts[:username],opts[:password],:login) if opts.has_key?(:username) and opts.has_key?(:password)
862
-
863
- smtp = Net::SMTP.new(opts[:server], opts[:port])
864
- smtp.enable_starttls if opts[:tls]
907
+ # execute template
908
+ msg_with_headers=ERB.new(notif_template).result(template_binding)
909
+ Log.dump(:msg_with_headers,msg_with_headers)
910
+ smtp = Net::SMTP.new(mail_conf[:server], mail_conf[:port])
911
+ smtp.enable_starttls if mail_conf[:tls]
865
912
  smtp.start(*start_options) do |smtp|
866
- smtp.send_message(msg, email[:from_email], email[:to])
913
+ smtp.send_message(msg_with_headers, vars[:from_email], vars[:to])
867
914
  end
868
915
  end
869
916
 
870
917
  def save_presets_to_config_file
871
918
  raise 'no configuration loaded' if @config_presets.nil?
872
919
  FileUtils.mkdir_p(@main_folder) unless Dir.exist?(@main_folder)
873
- Log.log.debug "writing #{@option_config_file}"
920
+ Log.log.debug("Writing #{@option_config_file}")
874
921
  File.write(@option_config_file,@config_presets.to_yaml)
875
922
  end
876
923