kafo 5.0.0 → 6.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 97ef9adc77292287d8396442c06918f89a4c893d8fb4b2b18cd308349b6ad343
4
- data.tar.gz: e2fee5ed65cf1fd277749132294bb0c4e6f9edf6bbdba40234d518be148c46c1
3
+ metadata.gz: a9ce6e0d19780eb90d3fce6d40bdb0cc6dad3c249e5f3462cbcfbc5c785abd95
4
+ data.tar.gz: 0acbff7b82150ef61629a12bae8769c11fbf509e7458ebe39288493774bdcacf
5
5
  SHA512:
6
- metadata.gz: 2baefdc6ee7b76d1bdbcf201f80678482896f885bb2f35d119241e41c380a6b6780ba41283a7e511c0c00cb958b56c3b715d4c87e2d9fc4e4ddfde8eab41e255
7
- data.tar.gz: 66040a434d464ac4a83923c83fecb6d1998e7a1dd292331d2d6e018a3db229c50b952ada9e5a3b2cfc673d746f4aa4e32479ef4a139015b1ce0f674c087a938a
6
+ metadata.gz: 3a829dd674a2a4c21593b72b15fd348dcea9f7c555c02a3d3ebcfc3f84fa24abc1f46a38586399e539114a0020c74841efa4622a3b0a4b732e72dfbebe321369
7
+ data.tar.gz: d047bafa9ee5b763c14c66f8dd5dfed0f35a2c18babd2609e7567b7d02b8379dd54ac07afe779fc0eb64032bc9044623e86f29f0ce16ce0385a9579f5e8b2235
data/README.md CHANGED
@@ -736,6 +736,7 @@ We currently support the following hooks.
736
736
  * pre_commit - after validations or interactive wizard have completed, all parameter values are set but not yet stored in the answer file
737
737
  * pre - just before puppet is executed to converge system, after parameter values are stored in the answer file
738
738
  * post - just after puppet is executed to converge system
739
+ * pre_exit - happens during exit handling, before exit is completed
739
740
 
740
741
  For better understanding when the hooks are executed see the [diagram](doc/kafo_run.png).
741
742
 
Binary file
@@ -105,5 +105,7 @@
105
105
 
106
106
  #Greenyellow:**post**|
107
107
 
108
+ #Greenyellow:**pre_exit**|
109
+
108
110
  stop
109
111
  @enduml
@@ -0,0 +1,19 @@
1
+ require_relative 'definition'
2
+
3
+ module Kafo
4
+ module AppOption
5
+ module Declaration
6
+
7
+ include Clamp::Option::Declaration
8
+
9
+ def app_option(switches, type, description, opts = {}, &block)
10
+ AppOption::Definition.new(switches, type, description, opts).tap do |option|
11
+ block ||= option.default_conversion_block
12
+ define_accessors_for(option, &block)
13
+ declared_options << option
14
+ end
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ module Kafo
2
+ module AppOption
3
+ class Definition < Clamp::Option::Definition
4
+
5
+ def initialize(switches, type, description, options = {})
6
+ @advanced = options.fetch(:advanced, false)
7
+ super(switches, type, description, options)
8
+ end
9
+
10
+ def advanced?
11
+ @advanced
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -15,9 +15,11 @@ module Kafo
15
15
  :description => '',
16
16
  :enabled => true,
17
17
  :log_dir => '/var/log/kafo',
18
+ :log_owner => nil,
19
+ :log_group => nil,
18
20
  :store_dir => '',
19
21
  :log_name => 'configuration.log',
20
- :log_level => 'info',
22
+ :log_level => 'notice',
21
23
  :no_prefix => false,
22
24
  :mapping => {},
23
25
  :answer_file => './config/answers.yaml',
@@ -26,11 +28,20 @@ module Kafo
26
28
  :colors => Kafo::ColorScheme.colors_possible?,
27
29
  :color_of_background => :dark,
28
30
  :hook_dirs => [],
31
+ :check_dirs => nil,
29
32
  :custom => {},
30
33
  :facts => {},
31
34
  :low_priority_modules => [],
32
- :verbose_log_level => 'info',
33
- :skip_puppet_version_check => false
35
+ :verbose => false,
36
+ :verbose_log_level => 'notice',
37
+ :skip_puppet_version_check => false,
38
+ :parser_cache_path => nil,
39
+ :ignore_undocumented => nil,
40
+ :order => nil,
41
+ :hiera_config => nil,
42
+ :kafo_modules_dir => nil,
43
+ :config_header_file => nil,
44
+ :dont_save_answers => nil,
34
45
  }
35
46
 
36
47
  def self.get_scenario_id(filename)
@@ -57,10 +68,17 @@ module Kafo
57
68
 
58
69
  def save_configuration(configuration)
59
70
  return true unless @persist
71
+
72
+ trimmed = configuration.reject do |key, value|
73
+ !DEFAULT.key?(key) || value.nil?
74
+ end
75
+
60
76
  begin
61
77
  FileUtils.touch @config_file
62
78
  File.chmod 0600, @config_file
63
- File.open(@config_file, 'w') { |file| file.write(format(YAML.dump(configuration))) }
79
+ File.open(@config_file, 'w') do |file|
80
+ file.write(format(YAML.dump(trimmed.sort.to_h)))
81
+ end
64
82
  rescue Errno::EACCES
65
83
  puts "Insufficient permissions to write to #{@config_file}, can not continue"
66
84
  KafoConfigure.exit(:insufficient_permissions)
@@ -104,6 +122,10 @@ module Kafo
104
122
  custom_fact_storage[key.to_s] = value
105
123
  end
106
124
 
125
+ def has_custom_fact?(key)
126
+ custom_fact_storage.key?(key.to_s)
127
+ end
128
+
107
129
  def modules
108
130
  @modules ||= begin
109
131
  register_data_types
@@ -175,7 +197,7 @@ module Kafo
175
197
  }
176
198
  EOS
177
199
 
178
- @logger.info 'Loading default values from puppet modules...'
200
+ @logger.notice 'Loading default values from puppet modules...'
179
201
  command = PuppetCommand.new(dump_manifest, [], puppetconf, self).command
180
202
  stdout, stderr, status = Open3.capture3(*PuppetCommand.format_command(command))
181
203
 
@@ -200,7 +222,7 @@ EOS
200
222
  end
201
223
  end
202
224
 
203
- @logger.info "... finished"
225
+ @logger.notice "... finished"
204
226
 
205
227
  load_yaml_from_output(stdout.split($/))
206
228
  end
@@ -305,7 +327,7 @@ EOS
305
327
  save_configuration(app)
306
328
  store(answers)
307
329
  migrations.store_applied
308
- @logger.info("#{migrations.migrations.count} migration/s were applied. Updated configuration was saved.")
330
+ @logger.notice("#{migrations.migrations.count} migration/s were applied. Updated configuration was saved.")
309
331
  end
310
332
  migrations.migrations.count
311
333
  end
@@ -26,8 +26,8 @@ module Kafo
26
26
  def exit(code, &block)
27
27
  @exit_code = translate_exit_code(code)
28
28
  block.call if block
29
+ KafoConfigure.hooking.execute(:pre_exit, log_stage: false)
29
30
  logger.debug "Exit with status code: #{@exit_code} (signal was #{code})"
30
- logger.dump_errors unless KafoConfigure.verbose
31
31
  cleanup
32
32
  Kernel.exit(@exit_code)
33
33
  end
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Kafo
4
4
  module HelpBuilders
5
- DEFAULT_GROUP_NAME = 'Basic'
6
- DEFAULT_MODULE_NAME = 'Generic'
5
+ DEFAULT_GROUP_NAME = 'Basic'
6
+ DEFAULT_MODULE_NAME = 'Generic'
7
7
  IGNORE_IN_GROUP_NAME = /\s*parameters:?/
8
8
 
9
9
  class Base < Clamp::Help::Builder
@@ -15,12 +15,14 @@ module Kafo
15
15
  end
16
16
 
17
17
  def add_list(heading, items)
18
+ return if items.empty?
18
19
  if heading == 'Options'
19
20
  puts "\n#{heading}:"
20
21
 
21
22
  data = by_module(items)
23
+
22
24
  sorted_keys(data).each do |section|
23
- if section == 'Generic'
25
+ if section == DEFAULT_MODULE_NAME
24
26
  add_list(header(1, section), data[section])
25
27
  else
26
28
  add_module(section, data[section])
@@ -4,8 +4,15 @@ module Kafo
4
4
  module HelpBuilders
5
5
  class Basic < Base
6
6
  def add_module(name, items)
7
- data = by_parameter_groups(except_resets(items))
8
- add_list(module_header(name), data['Basic'])
7
+ pruned = except_resets(items)
8
+ pruned = except_advanced(pruned)
9
+ data = by_parameter_groups(pruned)
10
+ add_list(module_header(name), data[DEFAULT_GROUP_NAME])
11
+ end
12
+
13
+ def add_list(heading, items)
14
+ pruned = except_advanced(items)
15
+ super(heading, pruned)
9
16
  end
10
17
 
11
18
  def string
@@ -17,6 +24,10 @@ module Kafo
17
24
  def except_resets(items)
18
25
  items.select { |i| !i.help.first.strip.start_with?('--reset-') || !i.help.last.include?('to the default value (') }
19
26
  end
27
+
28
+ def except_advanced(items)
29
+ items.reject { |item| item.respond_to?(:advanced?) && item.advanced? }
30
+ end
20
31
  end
21
32
  end
22
33
  end
@@ -3,28 +3,36 @@ require 'kafo/base_context'
3
3
 
4
4
  module Kafo
5
5
  class HookContext < BaseContext
6
+ # @return [Kafo::KafoConfigure]
6
7
  attr_reader :kafo
7
8
 
8
- def self.execute(kafo, &hook)
9
- new(kafo).instance_eval(&hook)
10
- end
11
-
12
- def initialize(kafo)
13
- @kafo = kafo
14
- end
15
-
16
9
  # some of hooks won't print any message because logger is not yet configured
17
10
  # configuration of logger depends on application configration (log level etc.)
18
- # examples:
11
+ #
12
+ # @return [Kafo::Logger]
13
+ #
14
+ # @example
19
15
  # logger.warn "this combindation of parameters is untested"
20
- def logger
21
- self.kafo.logger
16
+ attr_reader :logger
17
+
18
+ def self.execute(kafo, logger, &hook)
19
+ new(kafo, logger).instance_eval(&hook)
20
+ end
21
+
22
+ def initialize(kafo, logger)
23
+ @kafo = kafo
24
+ @logger = logger
22
25
  end
23
26
 
24
27
  # if you want to add new app_option be sure to do as soon as possible (usually boot hook)
25
28
  # otherwise it may be too late (e.g. when displaying help)
26
- # examples:
29
+ #
30
+ # @return [Clamp::Option]
31
+ #
32
+ # @example
27
33
  # app_option '--log-level', 'LEVEL', 'Log level for log file output', :default => config.app[:log_level]:
34
+ #
35
+ # @example
28
36
  # app_option ['-n', '--noop'], :flag, 'Run puppet in noop mode?', :default => false
29
37
  def app_option(*args)
30
38
  self.kafo.class.app_option(*args)
@@ -32,19 +40,34 @@ module Kafo
32
40
 
33
41
  # Returns whether the given app option exists. This is useful when there's a conditional option that is
34
42
  # determined during boot; this helper can be used in later hooks to determine whether the option exists.
43
+ #
44
+ # @param [Symbol, String] option
35
45
  def app_option?(option)
36
46
  self.kafo.config.app.key?(option.to_sym)
37
47
  end
38
48
 
39
- # examples:
49
+ # @param [Symbol, String] option
50
+ #
51
+ # @example
40
52
  # app_value(:log_level)
53
+ #
41
54
  # note the dash to underscore convention
42
55
  def app_value(option)
43
56
  self.kafo.config.app[option.to_sym]
44
57
  end
45
58
 
46
- # examples:
59
+ # Return the parameter of a module. Note that the module may not actually
60
+ # be enabled.
61
+ #
62
+ # @param [String] module_name
63
+ # @param [String] parameter_name
64
+ #
65
+ # @return [Kafo::Param, nil]
66
+ #
67
+ # @example
47
68
  # param('foreman', 'interface').value = 'eth0'
69
+ #
70
+ # @example
48
71
  # param('foreman', 'interface').value = app_option('bind_on_interface')
49
72
  def param(module_name, parameter_name)
50
73
  self.kafo.param(module_name, parameter_name)
@@ -55,8 +78,14 @@ module Kafo
55
78
  # part of answer file so it also preserves parameter values between runs. It also list
56
79
  # its options in help output. You can also specify mapping for this module as a second
57
80
  # parameter.
58
- # examples:
81
+ #
82
+ # @param [String] module_name
83
+ # @param [Hash, nil] mapping
84
+ #
85
+ # @example
59
86
  # add_module('my_module')
87
+ #
88
+ # @example
60
89
  # add_module('foreman::plugin::staypuft', {:dir_name => 'foreman', :manifest_name => 'plugin/staypuft'})
61
90
  def add_module(module_name, mapping = nil)
62
91
  self.kafo.config.add_mapping(module_name, mapping) if mapping
@@ -64,7 +93,10 @@ module Kafo
64
93
  end
65
94
 
66
95
  # Check if a module is enabled in the current configuration.
67
- # examples:
96
+ #
97
+ # @param [String] module_name
98
+ #
99
+ # @example
68
100
  # module_enabled?('example')
69
101
  def module_enabled?(module_name)
70
102
  mod = self.kafo.module(module_name)
@@ -72,7 +104,10 @@ module Kafo
72
104
  end
73
105
 
74
106
  # Check if a module is present in the current configuration.
75
- # examples:
107
+ #
108
+ # @param [String] module_name
109
+ #
110
+ # @example
76
111
  # module_present?('example')
77
112
  def module_present?(module_name)
78
113
  mod = self.kafo.module(module_name)
@@ -82,51 +117,84 @@ module Kafo
82
117
  # You can trigger installer exit by this method. You must specify exit code as a first
83
118
  # argument. You can also specify a symbol alias which is built-in (see exit_handler.rb
84
119
  # for more details).
85
- # examples:
120
+ #
121
+ # @param [Integer, Symbol] code
122
+ #
123
+ # @example
86
124
  # exit(0)
125
+ #
126
+ # @example
87
127
  # exit(:manifest_error)
88
128
  def exit(code)
89
129
  self.kafo.class.exit(code)
90
130
  end
91
131
 
92
132
  # You can load a custom config value that has been saved using store_custom_config
133
+ #
134
+ # @param [Symbol] key
93
135
  def get_custom_config(key)
94
136
  self.kafo.config.get_custom(key)
95
137
  end
96
138
 
97
139
  # You can save any value into kafo configuration file, this is useful if you need to
98
140
  # share a value between more hooks and persist the values for next run
141
+ #
142
+ # @param [Symbol] key
143
+ # @param [Object] value
99
144
  def store_custom_config(key, value)
100
145
  self.kafo.config.set_custom(key, value)
101
146
  end
102
147
 
103
148
  # Load a custom fact from the custom fact storage as saved by store_custom_fact
149
+ #
150
+ # @param [Symbol] key
104
151
  def get_custom_fact(key)
105
152
  self.kafo.config.get_custom_fact(key)
106
153
  end
107
154
 
108
- # Store a any custom fact. This will show up as kafo.scenario.custom.your_fact.
155
+ # Store any custom fact. This will show up as kafo.scenario.custom.your_fact.
109
156
  # It is possible to use structures such as arrays and hashes besides the
110
157
  # obvious ones such as strings, integers, booleans.
111
158
  #
112
159
  # These facts can also be used in Hiera hierachy definitions.
160
+ #
161
+ # @param [Symbol] key
162
+ # @param [Object] value
113
163
  def store_custom_fact(key, value)
114
164
  self.kafo.config.set_custom_fact(key, value)
115
165
  end
116
166
 
167
+ # Check whether a custom fact exists, regardless of whether or not it has a value.
168
+ #
169
+ # @param [Symbol] key
170
+ def has_custom_fact?(key)
171
+ self.kafo.config.has_custom_fact?(key)
172
+ end
173
+
117
174
  # Return the id of the current scenario
175
+ #
176
+ # @return [String]
118
177
  def scenario_id
119
178
  self.kafo.config.scenario_id
120
179
  end
121
180
 
122
181
  # Return the path to the current scenario
182
+ #
183
+ # @return [String]
123
184
  def scenario_path
124
185
  self.kafo.config.config_file
125
186
  end
126
187
 
127
188
  # Return the actual data in the current scenario
189
+ #
190
+ # @return [Hash]
128
191
  def scenario_data
129
192
  self.kafo.config.app
130
193
  end
194
+
195
+ # Return the current exit code
196
+ def exit_code
197
+ self.kafo.exit_code
198
+ end
131
199
  end
132
200
  end
@@ -2,15 +2,16 @@ require 'kafo/hook_context'
2
2
 
3
3
  module Kafo
4
4
  class Hooking
5
- # pre_migrations - just after kafo reads its configuration - useful for config file updates. Only in this stage it is posible to request config reload (`Kafo.request_config_reload`) to get in our changes
6
- # boot - before kafo is ready to work, useful for adding new app arguments, logger won't work yet
7
- # init - just after hooking is initialized and kafo is configured, parameters have no values yet
8
- # pre_values - just before value from CLI is set to parameters (they already have default values)
9
- # pre_validations - just after system checks and before validations are executed (and before interactive wizard is started), at this point all parameter values are already set but not yet stored in answer file
10
- # pre_commit - after validations or interactive wizard have completed, all parameter values are set but not yet stored in the answer file
11
- # pre - just before puppet is executed to converge system
12
- # post - just after puppet is executed to converge system
13
- TYPES = [:pre_migrations, :boot, :init, :pre, :post, :pre_values, :pre_validations, :pre_commit]
5
+ # * pre_migrations - just after kafo reads its configuration - useful for config file updates. Only in this stage it is posible to request config reload (`Kafo.request_config_reload`) to get in our changes
6
+ # * boot - before kafo is ready to work, useful for adding new app arguments, logger won't work yet
7
+ # * init - just after hooking is initialized and kafo is configured, parameters have no values yet
8
+ # * pre_values - just before value from CLI is set to parameters (they already have default values)
9
+ # * pre_validations - just after system checks and before validations are executed (and before interactive wizard is started), at this point all parameter values are already set but not yet stored in answer file
10
+ # * pre_commit - after validations or interactive wizard have completed, all parameter values are set but not yet stored in the answer file
11
+ # * pre - just before puppet is executed to converge system
12
+ # * post - just after puppet is executed to converge system
13
+ # * pre_exit - happens during exit handling, before exit is completed
14
+ TYPES = [:pre_migrations, :boot, :init, :pre_values, :pre_validations, :pre_commit, :pre, :post, :pre_exit]
14
15
 
15
16
  attr_accessor :hooks, :kafo
16
17
 
@@ -44,14 +45,16 @@ module Kafo
44
45
  @loaded
45
46
  end
46
47
 
47
- def execute(group)
48
- logger.info "Executing hooks in group #{group}"
48
+ def execute(group, log_stage: true)
49
+ logger = Logger.new(group)
50
+ logger.notice "Executing hooks in group #{group}" if log_stage
49
51
  self.hooks[group].keys.sort_by(&:to_s).each do |name|
50
52
  hook = self.hooks[group][name]
51
- result = HookContext.execute(self.kafo, &hook)
53
+ result = HookContext.execute(self.kafo, logger, &hook)
52
54
  logger.debug "Hook #{name} returned #{result.inspect}"
53
55
  end
54
- logger.info "All hooks in group #{group} finished"
56
+ logger.notice "All hooks in group #{group} finished" if log_stage
57
+ @group = nil
55
58
  end
56
59
 
57
60
  def register_pre_migrations(name, &block)
@@ -86,6 +89,10 @@ module Kafo
86
89
  register(:post, name, &block)
87
90
  end
88
91
 
92
+ def register_pre_exit(name, &block)
93
+ register(:pre_exit, name, &block)
94
+ end
95
+
89
96
  private
90
97
 
91
98
  def register(group, name, &block)