kafo 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of kafo might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cec1cec4f897c23ed85f473caca2b1e9fc7feea7
4
- data.tar.gz: 5cd2bb6b161e2fdbf71e42425df0179cad53226b
3
+ metadata.gz: b6baa0a37138d0cf9c3507b1447bd5f67d7f081b
4
+ data.tar.gz: d48cdf33c7943f2108e8a02d10a575a2cec960d3
5
5
  SHA512:
6
- metadata.gz: ad300f9ee839582ea0b81b26861f75347280f9ab746bcf7c70130141c430f7dcf5da98e62671912053c5bb4e0fe98b4feb8020af63468288dbee5681909643e7
7
- data.tar.gz: 7ea593a6fda67a94dbb9daaa88ac9138086e974d7fec9c62737c76145445334e8ef783dae6ffab8a99f3253525e4f45bed55640a9b1a9e4d8c81aa5d6d79ae35
6
+ metadata.gz: 8fbce457e4181cee9428bbc92ecbae2adb3714f0b4813ec155cbd345c56ab9468e2d39becfba8e638ab671fb22e7a9ceec72608e1027a045cb15284566f53384
7
+ data.tar.gz: 8e70ebdd67e493754da42ca37750f39bc650dd2357f89f9875331318b1fe54d0463f22299cad7b9128afe956d0aafb4afc21752cf3608e7a63083f7e6092ad84
data/README.md CHANGED
@@ -488,41 +488,92 @@ It also works in interactive mode.
488
488
  ## Hooks
489
489
 
490
490
  You may need to add new features to the installer. Kafo provides simple hook
491
- mechanism that allows you to run custom code just before and after the puppet
492
- is ran. Let's assume we want to add --reset-foreman-db option to our
493
- foreman-installer. We add following lines to generated installer script
491
+ mechanism that allows you to run custom code at various time. We support
492
+ several hooks.
493
+
494
+ * boot - before kafo is ready to work, useful for adding new installer arguments, logger won't work yet
495
+ * init - just after hooking is initialized and kafo is configured, parameters have no values yet
496
+ * pre_values - just before value from CLI is set to parameters (they already have default values)
497
+ * pre - just before puppet is executed to converge system
498
+ * post - just after puppet is executed to converge system
499
+
500
+ Let's assume we want to add --reset-foreman-db option to our
501
+ foreman-installer. We could either add following lines to generated
502
+ installer script.
494
503
 
495
504
  ```ruby
496
505
  require 'kafo/hooking'
497
506
 
498
- # functions specific to foreman installer
499
- KafoConfigure.app_option '--reset-foreman-db',
500
- :flag, 'Drop foreman database first? You will lose all data!', :default => false
507
+ # first hook that creates new app option --reset-foreman-db
508
+ KafoConfigure.hooking.register_boot(:add_reset_option) do
509
+ app_option '--reset-foreman-db',
510
+ :flag, 'Drop foreman database first? You will lose all data!', :default => false
511
+ end
501
512
 
502
- KafoConfigure.hooking.register_pre(:reset_db) do |kafo|
503
- if kafo.config.app[:reset_foreman_db] && !kafo.config.app[:noop]
513
+ # second hook which resets the db if value was set to true
514
+ KafoConfigure.hooking.register_pre(:reset_db) do
515
+ if app_value(:reset_foreman_db) && !app_value(:noop)
504
516
  `which foreman-rake > /dev/null 2>&1`
505
517
  if $?.success?
506
- KafoConfigure.logger.info 'Dropping database!'
518
+ logger.info 'Dropping database!'
507
519
  output = `foreman-rake db:drop 2>&1`
508
- KafoConfigure.logger.debug output.to_s
520
+ logger.debug output.to_s
509
521
  unless $?.success?
510
- KafoConfigure.logger.warn "Unable to drop DB, ignoring since it's not fatal, output was: '#{output}''"
522
+ logger.warn "Unable to drop DB, ignoring since it's not fatal, output was: '#{output}''"
511
523
  end
512
524
  else
513
- KafoConfigure.logger.warn 'Foreman not installed yet, can not drop database!'
525
+ logger.warn 'Foreman not installed yet, can not drop database!'
526
+ end
527
+ end
528
+ end
529
+ ```
530
+
531
+ Note that the hook is evaluated in HookContext object which provides some DSL. We can create
532
+ new installer option using ```app_option```. These option values can be accessed by using
533
+ ```app_value(:reset_foreman_db)```. You can modify parameters (if they are already defined)
534
+ using ```param('module name', 'parameter name')``` accessor. Last but not least you have
535
+ access to logger. For more details, see hook_context.rb.
536
+
537
+ If you don't want to modify you installer script you can place your hooks into
538
+ hooks directory. By default hooks dir is searched for ruby files in subdirectories
539
+ based on hook type. For example pre hooks are searched for in ```$installer_dir/hooks/pre/*.rb```
540
+ Hooks from previous example would look like this. The only change to the code is
541
+ that you don't explicitely register hooks, it's done automatically for you.
542
+
543
+ ```ruby
544
+ # hooks/boot/10-add_reset_option.rb
545
+ app_option '--reset-foreman-db', :flag, 'Drop foreman database first? You will lose all data!', :default => false
546
+ ```
547
+
548
+ ```ruby
549
+ # hooks/pre/10-reset_option_feature.rb
550
+ if app_value(:reset_foreman_db) && !app_value(:noop)
551
+ `which foreman-rake > /dev/null 2>&1`
552
+ if $?.success?
553
+ logger.info 'Dropping database!'
554
+ output = `foreman-rake db:drop 2>&1`
555
+ logger.debug output.to_s
556
+ unless $?.success?
557
+ logger.warn "Unable to drop DB, ignoring since it's not fatal, output was: '#{output}''"
514
558
  end
559
+ else
560
+ logger.warn 'Foreman not installed yet, can not drop database!'
515
561
  end
516
562
  end
517
563
  ```
518
564
 
519
- Note that we can access other installer options using ```kafo.config.app```. Since ```kafo``` is
520
- KafoConfigure instance, you can even access puppet params values. Last but not least you have
521
- access to logger.
522
565
 
523
- You can register as many hooks as you need. They are executed in unspecified order. Every hook
524
- must have a unique name. In a very similar way you can register :post hooks that are executed
525
- right after puppet run is over.
566
+ If you want to add more directories to be search you can use hook_dirs option
567
+ in installer configuration file.
568
+
569
+ ```yaml
570
+ :hook_dirs:
571
+ - /opt/hooks
572
+ - /my/plugin/hooks
573
+ ```
574
+
575
+ You can register as many hooks as you need. The order of execution for particular hook type
576
+ is based on hook file name.
526
577
 
527
578
  ## Colors
528
579
 
data/bin/kafofy CHANGED
@@ -30,7 +30,7 @@ options[:name] ||= "kafo-configure"
30
30
  options[:config_file] ||= "./config/#{options[:name]}.yaml"
31
31
 
32
32
  # Create directory structure
33
- %w(bin config modules).each do |dir|
33
+ %w(bin config modules hooks).each do |dir|
34
34
  FileUtils.mkdir_p dir
35
35
  end
36
36
 
@@ -36,3 +36,9 @@
36
36
  # :log_group: root
37
37
  # :config_header_file:
38
38
  # :dont_save_answers:
39
+
40
+ ## Hooks - hooks in these extra directories will be loaded,
41
+ # by default they are loaded from $installer_dir/hooks/$type
42
+ # when you specify your directory, it will be search for $yourdir/$type/*.rb
43
+ # :hooks_dir:
44
+ # - /opt/hooks
@@ -22,7 +22,8 @@ module Kafo
22
22
  :modules_dir => './modules',
23
23
  :default_values_dir => '/tmp',
24
24
  :colors => Configuration.colors_possible?,
25
- :color_of_background => :dark
25
+ :color_of_background => :dark,
26
+ :hook_dirs => []
26
27
  }
27
28
 
28
29
  def initialize(file, persist = true)
@@ -117,7 +118,11 @@ module Kafo
117
118
  private
118
119
 
119
120
  def includes
120
- modules.map { |mod| "include #{mod.dir_name}::params" }.join(' ')
121
+ modules.map do |mod|
122
+ params_file = File.join(KafoConfigure.modules_dir, modules.first.dir_name, 'manifests', 'params.pp')
123
+ @logger.debug "checking presence of #{params_file}"
124
+ File.exist?(params_file) ? "include #{mod.dir_name}::params" : nil
125
+ end.compact.join(' ')
121
126
  end
122
127
 
123
128
  def params
@@ -0,0 +1,51 @@
1
+ module Kafo
2
+ class HookContext
3
+ attr_reader :kafo
4
+
5
+ def self.execute(kafo, &hook)
6
+ # TODO can be removed in 0.6, is DEPRECATED since 0.5
7
+ # instance_exec can be later changed to instance eval when people stop using |kafo| in their hooks
8
+ # and rely only on hook context DSL
9
+ if hook.arity > 0
10
+ kafo.logger.warn "Hook '#{name}' is using block with arguments which is DEPRECATED, access to kafo instance is " +
11
+ "provided by hook DSL, please remove |kafo| from your hook block"
12
+ end
13
+ new(kafo).instance_exec(kafo, &hook)
14
+ end
15
+
16
+ def initialize(kafo)
17
+ @kafo = kafo
18
+ end
19
+
20
+ # some of hooks won't print any message because logger is not yet configured
21
+ # configuration of logger depends on application configration (log level etc.)
22
+ # examples:
23
+ # logger.warn "this combindation of parameters is untested"
24
+ def logger
25
+ self.kafo.logger
26
+ end
27
+
28
+ # if you want to add new app_option be sure to do as soon as possible (usually boot hook)
29
+ # otherwise it may be to late (e.g. when displaying help)
30
+ # examples:
31
+ # app_option '--log-level', 'LEVEL', 'Log level for log file output', :default => config.app[:log_level]:
32
+ # app_option ['-n', '--noop'], :flag, 'Run puppet in noop mode?', :default => false
33
+ def app_option(*args)
34
+ self.kafo.class.app_option *args
35
+ end
36
+
37
+ # examples:
38
+ # app_value(:log_level)
39
+ # note the dash to underscore convention
40
+ def app_value(option)
41
+ self.kafo.config.app[option.to_sym]
42
+ end
43
+
44
+ # examples:
45
+ # param('foreman', 'interface').value = 'eth0'
46
+ # param('foreman', 'interface').value = app_option('bind_on_interface')
47
+ def param(module_name, parameter_name)
48
+ self.kafo.param(module_name, parameter_name)
49
+ end
50
+ end
51
+ end
@@ -1,25 +1,67 @@
1
+ require 'kafo/hook_context'
2
+
1
3
  module Kafo
2
4
  class Hooking
5
+ # boot - before kafo is ready to work, useful for adding new app arguments, logger won't work yet
6
+ # init - just after hooking is initialized and kafo is configured, parameters have no values yet
7
+ # pre_values - just before value from CLI is set to parameters (they already have default values)
8
+ # pre - just before puppet is executed to converge system
9
+ # post - just after puppet is executed to converge system
10
+ TYPES = [:boot, :init, :pre, :post, :pre_values]
3
11
 
4
12
  attr_accessor :hooks, :kafo
5
13
 
6
14
  def initialize
7
15
  self.hooks = Hash.new { |h, k| h[k] = {} }
16
+ @loaded = false
8
17
  end
9
18
 
10
19
  def logger
11
20
  KafoConfigure.logger
12
21
  end
13
22
 
23
+ def load
24
+ base_dirs = [File.join([KafoConfigure.root_dir, 'hooks']), KafoConfigure.config.app[:hook_dirs]]
25
+ base_dirs.each do |base_dir|
26
+ TYPES.each do |hook_type|
27
+ dir = File.join(base_dir, hook_type.to_s)
28
+ Dir.glob(dir + "/*.rb").sort.each do |file|
29
+ logger.debug "Loading hook #{file}"
30
+ hook = File.read(file)
31
+ hook_block = proc { instance_eval(hook, file, 1) }
32
+ register(hook_type, file, &hook_block)
33
+ end
34
+ end
35
+ @loaded = true
36
+ end
37
+ self
38
+ end
39
+
40
+ def loaded?
41
+ @loaded
42
+ end
43
+
14
44
  def execute(group)
15
45
  logger.info "Executing hooks in group #{group}"
16
46
  self.hooks[group].each_pair do |name, hook|
17
- result = hook.call(kafo)
47
+ result = HookContext.execute(self.kafo, &hook)
18
48
  logger.debug "Hook #{name} returned #{result.inspect}"
19
49
  end
20
50
  logger.info "All hooks in group #{group} finished"
21
51
  end
22
52
 
53
+ def register_boot(name, &block)
54
+ register(:boot, name, &block)
55
+ end
56
+
57
+ def register_init(name, &block)
58
+ register(:init, name, &block)
59
+ end
60
+
61
+ def register_pre_values(name, &block)
62
+ register(:pre_values, name, &block)
63
+ end
64
+
23
65
  def register_pre(name, &block)
24
66
  register(:pre, name, &block)
25
67
  end
@@ -9,6 +9,7 @@ end
9
9
 
10
10
  require 'pty'
11
11
  require 'clamp'
12
+ require 'kafo_parsers/exceptions'
12
13
  require 'kafo/exceptions'
13
14
  require 'kafo/configuration'
14
15
  require 'kafo/logger'
@@ -45,10 +46,12 @@ module Kafo
45
46
  self.class.gem_root = File.join(File.dirname(__FILE__), '../../')
46
47
  self.class.kafo_modules_dir = self.class.config.app[:kafo_modules_dir] || (self.class.gem_root + '/modules')
47
48
  @progress_bar = nil
49
+ self.class.hooking.load
48
50
  self.class.hooking.kafo = self
49
51
 
50
52
  super
51
53
 
54
+ self.class.hooking.execute(:boot)
52
55
  set_app_options
53
56
  # we need to parse app config params using clamp even before run method does it
54
57
  # so we limit parsing only to app config options (because of --help and later defined params)
@@ -57,6 +60,7 @@ module Kafo
57
60
  Logger.setup
58
61
  ColorScheme.new(config).setup
59
62
 
63
+ self.class.hooking.execute(:init)
60
64
  set_parameters # here the params gets parsed and we need app config populated
61
65
  set_options
62
66
  end
@@ -65,6 +69,10 @@ module Kafo
65
69
  self.class.config
66
70
  end
67
71
 
72
+ def logger
73
+ self.class.logger
74
+ end
75
+
68
76
  def execute
69
77
  catch :exit do
70
78
  parse_cli_arguments
@@ -174,19 +182,19 @@ module Kafo
174
182
 
175
183
  private
176
184
 
177
- def logger
178
- self.class.logger
179
- end
180
-
181
185
  def exit(code)
182
186
  self.class.exit(code)
183
187
  end
184
188
 
185
189
  def set_parameters
190
+ # set values based on default_values
186
191
  params.each do |param|
187
- # set values based on default_values
188
192
  param.set_default(config.params_default_values)
189
- # set values based on YAML
193
+ end
194
+
195
+ self.class.hooking.execute(:pre_values)
196
+ # set values based on YAML
197
+ params.each do |param|
190
198
  param.set_value_by_config(config)
191
199
  end
192
200
  end
@@ -296,7 +304,7 @@ module Kafo
296
304
  end
297
305
 
298
306
  def run_installation
299
- self.class.hooking.execute(:pre) if self.class.hooking
307
+ self.class.hooking.execute(:pre)
300
308
  exit_code = 0
301
309
  exit_status = nil
302
310
  options = [
@@ -333,7 +341,7 @@ module Kafo
333
341
  @progress_bar.close if @progress_bar
334
342
  logger.info "Puppet has finished, bye!"
335
343
  FileUtils.rm(temp_config_file, :force => true)
336
- self.class.hooking.execute(:post) if self.class.hooking
344
+ self.class.hooking.execute(:post)
337
345
  exit(exit_code)
338
346
  end
339
347
 
@@ -5,7 +5,11 @@ require 'logging'
5
5
  module Kafo
6
6
  class Logger
7
7
  class << self
8
- attr_accessor :loggers
8
+ attr_writer :loggers
9
+
10
+ def loggers
11
+ @loggers || []
12
+ end
9
13
  end
10
14
 
11
15
  PATTERN = "[%5l %d %c] %m\n"
@@ -25,6 +25,9 @@ module Kafo
25
25
  value = [value].flatten
26
26
  ::Hash[value.map { |v| v.split(':', 2) }]
27
27
  end
28
+ rescue NoMethodError => e
29
+ KafoConfigure.logger.warn "Could not typecast #{value} for parameter #{name}, defaulting to {}"
30
+ return {}
28
31
  end
29
32
  end
30
33
  end
@@ -10,6 +10,9 @@ module Kafo
10
10
 
11
11
  def typecast(value)
12
12
  value.nil? ? nil : value.to_i
13
+ rescue NoMethodError => e
14
+ KafoConfigure.logger.warn "Could not typecast #{value} for parameter #{name}, defaulting to 0"
15
+ return 0
13
16
  end
14
17
  end
15
18
  end
@@ -1,4 +1,4 @@
1
1
  # encoding: UTF-8
2
2
  module Kafo
3
- VERSION = "0.4.0"
3
+ VERSION = "0.5.0"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kafo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marek Hulan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-11 00:00:00.000000000 Z
11
+ date: 2014-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -217,6 +217,7 @@ files:
217
217
  - lib/kafo/hooking.rb
218
218
  - lib/kafo/string_helper.rb
219
219
  - lib/kafo/logger.rb
220
+ - lib/kafo/hook_context.rb
220
221
  - lib/kafo/color_scheme.rb
221
222
  - lib/kafo/param_group.rb
222
223
  - lib/kafo/progress_bars/colored.rb