kafo 0.0.1

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.

@@ -0,0 +1,65 @@
1
+ require 'puppet'
2
+ require 'rdoc'
3
+ # Based on ideas from puppet-parse by Johan van den Dorpe
4
+ class PuppetModuleParser
5
+ def self.parse(file)
6
+ content = new(file)
7
+
8
+ {
9
+ 'parameters' => content.parameters,
10
+ 'docs' => content.docs,
11
+ 'validations' => content.validations
12
+ }
13
+ end
14
+
15
+ def initialize(file)
16
+ raise ModuleName, "File not found #{file}, check you answer file" unless File.exists?(file)
17
+ parser = Puppet::Parser::Parser.new('production')
18
+ values = Puppet.settings.instance_variable_get('@values')
19
+ values[:production][:confdir] ||= '/' # just some stubbing
20
+ parser.import(file)
21
+
22
+ # Find object in list of hostclasses
23
+ parser.environment.known_resource_types.hostclasses.each do |x|
24
+ @object = x.last if x.last.file == file
25
+ end
26
+ # Find object in list of definitions
27
+ parser.environment.known_resource_types.definitions.each do |x|
28
+ @object = x.last if x.last.file == file
29
+ end
30
+ end
31
+
32
+ def parameters
33
+ parameters = {}
34
+ arguments = @object.respond_to?(:arguments) ? @object.arguments : {}
35
+ arguments.each { |k, v| parameters[k] = v.respond_to?(:value) ? v.value : nil }
36
+ parameters
37
+ end
38
+
39
+ def klass
40
+ @object.name if @object.class.respond_to?(:name)
41
+ end
42
+
43
+ def validations(param = nil)
44
+ @object.code.select { |stmt| stmt.is_a?(Puppet::Parser::AST::Function) && stmt.name =~ /^validate_/ }
45
+ end
46
+
47
+ def docs
48
+ docs = {}
49
+ if !@object.doc.nil?
50
+ rdoc = RDoc::Markup.parse(@object.doc)
51
+ items = rdoc.parts.select { |part| part.respond_to?(:items) }.map(&:items).flatten
52
+ items.each do |item|
53
+ # Skip rdoc items that aren't paragraphs
54
+ next unless (item.parts.to_s.scan("RDoc::Markup::Paragraph") == ["RDoc::Markup::Paragraph"])
55
+ # RDoc (>= 4) makes label an array
56
+ label = item.label.is_a?(Array) ? item.label.first : item.label
57
+ # Documentation must be a list - if there's no label then skip
58
+ next if label.nil?
59
+ key = label.tr('^A-Za-z0-9_-', '')
60
+ docs[key] = item.parts.first.parts.map!(&:strip)
61
+ end
62
+ end
63
+ docs
64
+ end
65
+ end
@@ -0,0 +1,19 @@
1
+ module StringHelper
2
+ def dashize(string)
3
+ string.tr('_', '-')
4
+ end
5
+ alias :d :dashize
6
+
7
+ def underscore(string)
8
+ string.tr('-', '_')
9
+ end
10
+ alias :u :underscore
11
+
12
+ def with_prefix(param)
13
+ "#{d(param.module_name)}-#{d(param.name)}"
14
+ end
15
+
16
+ def parametrize(param)
17
+ "--#{with_prefix(param)}"
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ # we require separate STDERR
2
+ require 'open3'
3
+
4
+ class SystemChecker
5
+ def self.check
6
+ new(File.join(KafoConfigure.root_dir, 'checks', '*')).check
7
+ end
8
+
9
+ def initialize(path)
10
+ @checkers = Dir.glob(path)
11
+ end
12
+
13
+ def logger
14
+ Logging::logger['checks']
15
+ end
16
+
17
+ def check
18
+ @checkers.map! do |checker|
19
+ logger.debug "Executing checker: #{checker}"
20
+ Open3.popen3(checker) { |stdin, stdout, stderr, wait_thr|
21
+ stdout = stdout.read
22
+ stderr = stderr.read
23
+ logger.debug stdout unless stdout.empty?
24
+ logger.error stderr unless stderr.empty?
25
+ wait_thr.value.success?
26
+ }
27
+ end
28
+
29
+ @checkers.all?
30
+ end
31
+ end
@@ -0,0 +1,59 @@
1
+ class Validator
2
+
3
+ def initialize(params)
4
+ files = KafoConfigure.root_dir + '/modules/stdlib/lib/puppet/parser/functions/validate_*.rb'
5
+ Dir.glob(files).each do |file|
6
+ require file
7
+ end
8
+
9
+ @params = params
10
+ @logger = Logging.logger.root
11
+
12
+ @cache ||= Hash.new do |hash, key|
13
+ @logger.debug "Looked for #{key}"
14
+ param = @params.select { |p| p.name == key.to_s }.first
15
+ hash[key] = param.nil? ? nil : param.value
16
+ end
17
+ end
18
+
19
+ def lookupvar(name, options = {})
20
+ @cache[name]
21
+ end
22
+
23
+ # for puppet >= 3
24
+ def include?(value)
25
+ true
26
+ end
27
+
28
+ # for puppet >= 3
29
+ def [](value, *args)
30
+ lookupvar(value)
31
+ end
32
+
33
+ def method_missing(method, *args, &block)
34
+ method.to_s =~ /^function_(.*)$/
35
+ super unless $1
36
+ super unless Puppet::Parser::Functions.function($1)
37
+ # In odd circumstances, this might not end up defined by the previous
38
+ # method, so we might as well be certain.
39
+ if engine.respond_to? method
40
+ @logger.debug "calling #{method.inspect} with #{args.inspect}"
41
+ engine.send(method, *args)
42
+ else
43
+ raise Puppet::DevError, "Function #{$1} not defined despite being loaded!"
44
+ end
45
+ rescue Puppet::ParseError => e
46
+ @logger.error e.message
47
+ return false
48
+ end
49
+
50
+ private
51
+
52
+ def engine
53
+ @engine ||= begin
54
+ klass = Class.new
55
+ klass.send :include, Puppet::Parser::Functions.environment_module
56
+ klass.new
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,3 @@
1
+ module Kafo
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,131 @@
1
+ # encoding: UTF-8
2
+ require 'highline/import'
3
+ require 'yaml'
4
+
5
+ class Wizard
6
+ def initialize
7
+ setup_terminal
8
+ setup_colors
9
+ @name = 'Kafo'
10
+ @config = KafoConfigure.config
11
+ end
12
+
13
+ def run
14
+ message = "Welcome to the #{@name} installer!"
15
+ say("<%= color('#{message}', :headline) %>")
16
+ say("<%= color('#{'-' * message.size}', :horizontal_line) %>")
17
+ say(<<END)
18
+
19
+ This wizard will gather all required information. You can change any parameter to your needs.
20
+
21
+ END
22
+
23
+ exit 0 unless agree("\n<%= color('Ready to start?', :question) %> (y/n)", false)
24
+
25
+ main_menu
26
+ end
27
+
28
+ private
29
+
30
+ def main_menu
31
+ finished = false
32
+ until finished
33
+ say("\n<%= color('Main Config Menu', :headline) %>")
34
+ choose do |menu|
35
+ menu.prompt = 'Choose an option from the menu... '
36
+ @config.modules.each do |mod|
37
+ menu.choice "[#{mod.enabled? ? '✓' : '✗'}] Configure #{mod.name}" do
38
+ configure_module(mod)
39
+ end
40
+ end
41
+ menu.choice "Display current config" do
42
+ display_hash
43
+ end
44
+ menu.choice "<%= color('Save and run', :run) %>" do
45
+ KafoConfigure.config
46
+ finished = true
47
+ end
48
+ menu.choice "<%= color('Cancel run without Saving', :cancel) %>" do
49
+ say("Bye!"); exit 0
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def display_hash
56
+ data = Hash[@config.modules.map { |mod| [mod.name, mod.enabled? ? mod.params_hash : false] }]
57
+ say "<%= color('#{YAML.dump data}', :info) %>"
58
+ end
59
+
60
+ def configure_module(mod)
61
+ go_back = false
62
+ until go_back
63
+ say("\n<%= color('Module #{mod.name} configuration', :headline) %>")
64
+ choose do |menu|
65
+ menu.prompt = 'Choose an option from the menu... '
66
+ menu.choice("Enable/disable #{mod.name} module, current value: <%= color('#{mod.enabled?}', :info) %>") { turn_module(mod) }
67
+ if mod.enabled?
68
+ mod.params.each do |param|
69
+ menu.choice "Set <%= color('#{param.name}', :important) %>, current value: <%= color('#{param.value}', :info) %>" do
70
+ configure(param)
71
+ end
72
+ end
73
+ end
74
+ menu.choice("Back to main menu") { go_back = true }
75
+ end
76
+ end
77
+ end
78
+
79
+ def configure(param)
80
+ say "\n<%= color('Parameter #{param.name} (of module #{param.module.name})', :headline) %>"
81
+ say "<%= color(\"#{param.doc.join("\n")}\", :important) %>"
82
+ value = param.multivalued? ? configure_multi(param) : configure_single(param)
83
+ value_was = param.value
84
+ param.value = value unless value.empty?
85
+
86
+ until param.valid?
87
+ param.value = value_was
88
+ say "\n<%= color('Invalid value for #{param.name}', :important) %>"
89
+ value = param.multivalued? ? configure_multi(param) : configure_single(param)
90
+ param.value = value unless value.empty?
91
+ end
92
+ end
93
+
94
+ def configure_single(param)
95
+ say "\ncurrent value: <%= color('#{param.value}', :info) %>"
96
+ ask("new value:")
97
+ end
98
+
99
+ def configure_multi(param)
100
+ say "<%= color('every line is a separate value, blank line to quit', :info) %>"
101
+ say "\ncurrent value: <%= color('#{param.value}', :info) %>"
102
+ ask("new value:") do |q|
103
+ q.gather = ""
104
+ end
105
+
106
+ end
107
+
108
+ def turn_module(mod)
109
+ agree("Enable #{mod.name} module? (y/n) ") ? mod.enable : mod.disable
110
+ end
111
+
112
+ def setup_terminal
113
+ $terminal = HighLine.new
114
+ data = HighLine::SystemExtensions.terminal_size
115
+ $terminal.wrap_at = data.first > 80 ? 80 : data.first
116
+ $terminal.page_at = data.last
117
+ end
118
+
119
+ # setup colour scheme for prompts
120
+ def setup_colors
121
+ HighLine.color_scheme = HighLine::ColorScheme.new do |cs|
122
+ cs[:headline] = [:bold, :yellow, :on_black]
123
+ cs[:horizontal_line] = [:bold, :white, :on_black]
124
+ cs[:important] = [:bold, :white, :on_black]
125
+ cs[:question] = [:bold, :green, :on_black]
126
+ cs[:info] = [:bold, :cyan, :on_black]
127
+ cs[:cancel] = [:bold, :red, :on_black]
128
+ cs[:run] = [:bold, :green, :on_black]
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,18 @@
1
+ # Translates module name to proper class name
2
+ # This is especially useful if you want to give a nice name to
3
+ # a configuration option and still want to use some class with
4
+ # less readable name e.g. puppetmaster -> puppet::server
5
+ # - if the argument matches known module name, it returns corresponding class name
6
+ # - otherwise it returns argument that was specified
7
+ #
8
+ module Puppet::Parser::Functions
9
+ newfunction(:class_name, :type => :rvalue) do |args|
10
+ case args[0]
11
+ when 'puppetmaster'
12
+ 'puppet::server'
13
+ else
14
+ args[0]
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,9 @@
1
+ # Find default values for variables specified as args
2
+ #
3
+ module Puppet::Parser::Functions
4
+ newfunction(:dump_values) do |args|
5
+ data = Hash[args.map { |arg| [arg, lookupvar(arg)] }]
6
+ File.write('config/default_values.yaml', YAML.dump(data))
7
+ end
8
+ end
9
+
@@ -0,0 +1,15 @@
1
+ # Takes a hash to extract keys from
2
+ # - If the first argument is not Hash, print warning and return nil
3
+ # - Returns array of hash keys otherwise
4
+ #
5
+ module Puppet::Parser::Functions
6
+ newfunction(:hash_keys, :type => :rvalue) do |args|
7
+ unless args[0].is_a?(Hash)
8
+ Puppet.warning "hash_keys takes one argument, the input hash"
9
+ nil
10
+ else
11
+ args[0].keys
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,22 @@
1
+ #
2
+ # is_hash.rb
3
+ #
4
+
5
+ module Puppet::Parser::Functions
6
+ newfunction(:is_hash, :type => :rvalue, :doc => <<-EOS
7
+ Returns true if the variable passed to this function is a hash.
8
+ EOS
9
+ ) do |arguments|
10
+
11
+ raise(Puppet::ParseError, "is_hash(): Wrong number of arguments " +
12
+ "given (#{arguments.size} for 1)") if arguments.size != 1
13
+
14
+ type = arguments[0]
15
+
16
+ result = type.is_a?(Hash)
17
+
18
+ return result
19
+ end
20
+ end
21
+
22
+ # vim: set ts=2 sw=2 et :
@@ -0,0 +1,37 @@
1
+ module Puppet::Parser::Functions
2
+
3
+ # convert nil values to :undefined recursively
4
+ newfunction(:convert, :type => :rvalue) do |args|
5
+ hash = args[0]
6
+ data = {}
7
+
8
+ hash.each do |key, value|
9
+ if value.is_a?(Hash)
10
+ data[key] = function_convert([value])
11
+ else
12
+ data[key] = value.nil? ? :undef : value
13
+ end
14
+ end
15
+
16
+ data
17
+ end
18
+
19
+ newfunction(:loadanyyaml, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
20
+ Load a YAML file containing an array, string, or hash, and return the data
21
+ in the corresponding native data type.
22
+
23
+ For example:
24
+
25
+ $myhash = loadanyyaml('/etc/puppet/data/myhash.yaml')
26
+ ENDHEREDOC
27
+
28
+ args.delete_if { |filename| not File.exist? filename }
29
+
30
+ if args.length == 0
31
+ raise Puppet::ParseError, ("loadanyyaml(): No files to load")
32
+ end
33
+
34
+ function_convert([YAML.load_file(args[0])])
35
+ end
36
+
37
+ end
@@ -0,0 +1,17 @@
1
+ # This class is called from the kafo configure script
2
+ # and expects a yaml file to exist at either:
3
+ # optional $answers class parameter
4
+ # $modulepath/config/answers.yaml
5
+ # /etc/kafo-configure/answers.yaml
6
+ #
7
+ class kafo_configure(
8
+ $answers = undef
9
+ ) {
10
+
11
+ $params = loadanyyaml($answers,
12
+ "/etc/kafo-configure/answers.yaml",
13
+ "config/answers.yaml")
14
+ $keys = hash_keys($params)
15
+
16
+ kafo_configure::yaml_to_class { $keys: }
17
+ }
@@ -0,0 +1,24 @@
1
+ # Takes a key to lookup in the installation answers file
2
+ # - If it's a hash, declare a class with those parameters
3
+ # - If it's true or "true" declare the default parameters for that class
4
+ # - If it's false or "false" ignore it
5
+ # - Otherwise fail with error
6
+ #
7
+ define kafo_configure::yaml_to_class {
8
+
9
+ $classname = class_name($name)
10
+
11
+ if is_hash($kafo_configure::params[$name]) {
12
+ # The quotes around $classname seem to matter to puppet's parser...
13
+ $params = { "${classname}" => $kafo_configure::params[$name] }
14
+ create_resources( 'class', $params )
15
+ } elsif $kafo_configure::params[$name] == true {
16
+ $params = { "${classname}" => {} }
17
+ create_resources( 'class', $params )
18
+ } elsif ! $kafo_configure::params[$name] or $kafo_configure::params[$name] == "false" {
19
+ debug("${::hostname}: not including $name")
20
+ } else {
21
+ fail("${::hostname}: unknown type of answers data for $name")
22
+ }
23
+
24
+ }