hiera-puppet 0.3.0 → 1.0.0rc2
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.
- data/bin/extlookup2hiera +26 -26
- data/lib/hiera/backend/puppet_backend.rb +87 -75
- data/lib/hiera/scope.rb +40 -39
- data/lib/hiera_puppet.rb +89 -0
- data/lib/puppet/parser/functions/hiera.rb +6 -43
- data/lib/puppet/parser/functions/hiera_array.rb +6 -34
- data/lib/puppet/parser/functions/hiera_hash.rb +6 -34
- data/lib/puppet/parser/functions/hiera_include.rb +9 -35
- data/spec/helpers.rb +0 -0
- data/spec/spec_helper.rb +6 -12
- data/spec/unit/hiera/backend/puppet_backend_spec.rb +143 -0
- data/spec/unit/hiera/scope_spec.rb +64 -0
- data/spec/unit/hiera_puppet_spec.rb +105 -0
- data/spec/unit/puppet/parser/functions/hiera_array_spec.rb +19 -0
- data/spec/unit/puppet/parser/functions/hiera_hash_spec.rb +19 -0
- data/spec/unit/puppet/parser/functions/hiera_include_spec.rb +19 -0
- data/spec/unit/puppet/parser/functions/hiera_spec.rb +21 -0
- data/spec/watchr.rb +79 -0
- metadata +36 -18
- data/spec/unit/puppet_backend_spec.rb +0 -118
- data/spec/unit/scope_spec.rb +0 -64
data/bin/extlookup2hiera
CHANGED
@@ -6,51 +6,51 @@ require 'csv'
|
|
6
6
|
options = {:in => nil, :out => nil, :format => :yaml}
|
7
7
|
|
8
8
|
OptionParser.new do |opts|
|
9
|
-
|
9
|
+
opts.banner = "Converter for extlookup CSV files into Hiera JSON and YAML files"
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
opts.on("--in FILE", "-i", "Input CSV file") do |v|
|
12
|
+
options[:in] = v
|
13
|
+
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
opts.on("--out FILE", "-o", "Output Hiera file") do |v|
|
16
|
+
options[:out] = v
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
opts.on("--json", "-j", "Create JSON format file") do |v|
|
20
|
+
options[:format] = :json
|
21
|
+
end
|
22
22
|
end.parse!
|
23
23
|
|
24
24
|
if options[:in].nil? || options[:out].nil?
|
25
|
-
|
26
|
-
|
25
|
+
STDERR.puts "Please specify an input and output file with --in and --out"
|
26
|
+
exit 1
|
27
27
|
end
|
28
28
|
|
29
29
|
unless File.exist?(options[:in])
|
30
|
-
|
31
|
-
|
30
|
+
STDERR.puts "Cannot find input file #{options[:in]}"
|
31
|
+
exit 1
|
32
32
|
end
|
33
33
|
|
34
34
|
csvdata = CSV.read(options[:in])
|
35
35
|
hieradata = {}
|
36
36
|
|
37
37
|
csvdata.each do |d|
|
38
|
-
|
38
|
+
d = d.map{|item| item.to_s}
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
if d.size > 2
|
41
|
+
hieradata[d[0]] = d[1, d.size].flatten
|
42
|
+
else
|
43
|
+
hieradata[d[0]] = d[1]
|
44
|
+
end
|
45
45
|
end
|
46
46
|
|
47
47
|
case options[:format]
|
48
48
|
when :yaml
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
require 'yaml'
|
50
|
+
File.open(options[:out], "w") {|f| f.write hieradata.to_yaml}
|
52
51
|
when :json
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
require 'rubygems'
|
53
|
+
require 'json'
|
54
|
+
File.open(options[:out], "w") {|f| f.write JSON.pretty_generate hieradata}
|
56
55
|
end
|
56
|
+
|
@@ -1,90 +1,102 @@
|
|
1
1
|
class Hiera
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
module Backend
|
3
|
+
class Puppet_backend
|
4
|
+
def initialize
|
5
|
+
Hiera.debug("Hiera Puppet backend starting")
|
6
|
+
end
|
7
|
+
|
8
|
+
def hierarchy(scope, override)
|
9
|
+
begin
|
10
|
+
data_class = Config[:puppet][:datasource] || "data"
|
11
|
+
rescue
|
12
|
+
data_class = "data"
|
13
|
+
end
|
7
14
|
|
8
|
-
|
9
|
-
|
10
|
-
data_class = Config[:puppet][:datasource] || "data"
|
11
|
-
rescue
|
12
|
-
data_class = "data"
|
13
|
-
end
|
15
|
+
calling_class = scope.resource.name.to_s.downcase
|
16
|
+
calling_module = calling_class.split("::").first
|
14
17
|
|
15
|
-
|
16
|
-
calling_module = calling_class.split("::").first
|
18
|
+
hierarchy = Config[:hierarchy] || [calling_class, calling_module]
|
17
19
|
|
18
|
-
|
20
|
+
hierarchy = [hierarchy].flatten.map do |klass|
|
21
|
+
klass = Backend.parse_string(klass, scope,
|
22
|
+
{
|
23
|
+
"calling_class" => calling_class,
|
24
|
+
"calling_module" => calling_module
|
25
|
+
}
|
26
|
+
)
|
19
27
|
|
20
|
-
|
21
|
-
klass = Backend.parse_string(klass, scope, {"calling_class" => calling_class, "calling_module" => calling_module})
|
28
|
+
next if klass == ""
|
22
29
|
|
23
|
-
|
30
|
+
[data_class, klass].join("::")
|
31
|
+
end.compact
|
24
32
|
|
25
|
-
|
26
|
-
end.compact
|
33
|
+
hierarchy << [calling_class, data_class].join("::")
|
27
34
|
|
28
|
-
|
29
|
-
|
35
|
+
unless calling_module == calling_class
|
36
|
+
hierarchy << [calling_module, data_class].join("::")
|
37
|
+
end
|
30
38
|
|
31
|
-
|
39
|
+
hierarchy.insert(0, [data_class, override].join("::")) if override
|
32
40
|
|
33
|
-
|
34
|
-
|
41
|
+
hierarchy
|
42
|
+
end
|
43
|
+
|
44
|
+
def lookup(key, scope, order_override, resolution_type)
|
45
|
+
answer = nil
|
46
|
+
|
47
|
+
Hiera.debug("Looking up #{key} in Puppet backend")
|
48
|
+
|
49
|
+
include_class = Puppet::Parser::Functions.function(:include)
|
50
|
+
loaded_classes = scope.catalog.classes
|
35
51
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
when :array
|
76
|
-
answer << Backend.parse_answer(temp_answer, scope)
|
77
|
-
else
|
78
|
-
answer = Backend.parse_answer(temp_answer, scope)
|
79
|
-
break
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
answer = nil if answer == :undefined
|
85
|
-
|
86
|
-
answer
|
52
|
+
hierarchy(scope, order_override).each do |klass|
|
53
|
+
Hiera.debug("Looking for data in #{klass}")
|
54
|
+
|
55
|
+
varname = [klass, key].join("::")
|
56
|
+
temp_answer = nil
|
57
|
+
|
58
|
+
unless loaded_classes.include?(klass)
|
59
|
+
begin
|
60
|
+
if scope.respond_to?(:function_include)
|
61
|
+
scope.function_include(klass)
|
62
|
+
else
|
63
|
+
scope.real.function_include(klass)
|
64
|
+
end
|
65
|
+
|
66
|
+
temp_answer = scope[varname]
|
67
|
+
Hiera.debug("Found data in class #{klass}")
|
68
|
+
rescue
|
69
|
+
end
|
70
|
+
else
|
71
|
+
temp_answer = scope[varname]
|
72
|
+
end
|
73
|
+
|
74
|
+
next if temp_answer == :undefined
|
75
|
+
|
76
|
+
if temp_answer
|
77
|
+
# For array resolution we just append to the array whatever we
|
78
|
+
# find, we then go onto the next file and keep adding to the array.
|
79
|
+
#
|
80
|
+
# For priority searches we break after the first found data item.
|
81
|
+
case resolution_type
|
82
|
+
when :array
|
83
|
+
answer ||= []
|
84
|
+
answer << Backend.parse_answer(temp_answer, scope)
|
85
|
+
when :hash
|
86
|
+
answer ||= {}
|
87
|
+
answer = Backend.parse_answer(temp_answer, scope).merge answer
|
88
|
+
else
|
89
|
+
answer = Backend.parse_answer(temp_answer, scope)
|
90
|
+
break
|
87
91
|
end
|
92
|
+
end
|
88
93
|
end
|
94
|
+
|
95
|
+
answer = nil if answer == :undefined
|
96
|
+
|
97
|
+
answer
|
98
|
+
end
|
89
99
|
end
|
100
|
+
end
|
90
101
|
end
|
102
|
+
|
data/lib/hiera/scope.rb
CHANGED
@@ -1,41 +1,42 @@
|
|
1
1
|
class Hiera
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
def include?(key)
|
24
|
-
return true if ["calling_class", "calling_module"].include?(key)
|
25
|
-
|
26
|
-
return @real.lookupvar(key) != ""
|
27
|
-
end
|
28
|
-
|
29
|
-
def catalog
|
30
|
-
@real.catalog
|
31
|
-
end
|
32
|
-
|
33
|
-
def resource
|
34
|
-
@real.resource
|
35
|
-
end
|
36
|
-
|
37
|
-
def compiler
|
38
|
-
@real.compiler
|
39
|
-
end
|
2
|
+
class Scope
|
3
|
+
attr_reader :real
|
4
|
+
|
5
|
+
def initialize(real)
|
6
|
+
@real = real
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](key)
|
10
|
+
if key == "calling_class"
|
11
|
+
ans = @real.resource.name.to_s.downcase
|
12
|
+
elsif key == "calling_module"
|
13
|
+
ans = @real.resource.name.to_s.downcase.split("::").first
|
14
|
+
else
|
15
|
+
ans = @real.lookupvar(key)
|
16
|
+
end
|
17
|
+
|
18
|
+
# damn you puppet visual basic style variables.
|
19
|
+
return nil if ans == ""
|
20
|
+
return ans
|
40
21
|
end
|
41
|
-
|
22
|
+
|
23
|
+
def include?(key)
|
24
|
+
return true if ["calling_class", "calling_module"].include?(key)
|
25
|
+
|
26
|
+
return @real.lookupvar(key) != ""
|
27
|
+
end
|
28
|
+
|
29
|
+
def catalog
|
30
|
+
@real.catalog
|
31
|
+
end
|
32
|
+
|
33
|
+
def resource
|
34
|
+
@real.resource
|
35
|
+
end
|
36
|
+
|
37
|
+
def compiler
|
38
|
+
@real.compiler
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
data/lib/hiera_puppet.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'hiera'
|
2
|
+
require 'hiera/scope'
|
3
|
+
require 'puppet'
|
4
|
+
|
5
|
+
module HieraPuppet
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def lookup(key, default, scope, override, resolution_type)
|
9
|
+
unless scope.respond_to?("[]")
|
10
|
+
scope = Hiera::Scope.new(scope)
|
11
|
+
end
|
12
|
+
|
13
|
+
answer = hiera.lookup(key, default, scope, override, resolution_type)
|
14
|
+
|
15
|
+
if answer.nil?
|
16
|
+
raise(Puppet::ParseError, "Could not find data item #{key} in any Hiera data file and no default supplied")
|
17
|
+
end
|
18
|
+
|
19
|
+
answer
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_args(args)
|
23
|
+
# Functions called from Puppet manifests like this:
|
24
|
+
#
|
25
|
+
# hiera("foo", "bar")
|
26
|
+
#
|
27
|
+
# Are invoked internally after combining the positional arguments into a
|
28
|
+
# single array:
|
29
|
+
#
|
30
|
+
# func = function_hiera
|
31
|
+
# func(["foo", "bar"])
|
32
|
+
#
|
33
|
+
# Functions called from templates preserve the positional arguments:
|
34
|
+
#
|
35
|
+
# scope.function_hiera("foo", "bar")
|
36
|
+
#
|
37
|
+
# Deal with Puppet's special calling mechanism here.
|
38
|
+
if args[0].is_a?(Array)
|
39
|
+
args = args[0]
|
40
|
+
end
|
41
|
+
|
42
|
+
if args.empty?
|
43
|
+
raise(Puppet::ParseError, "Please supply a parameter to perform a Hiera lookup")
|
44
|
+
end
|
45
|
+
|
46
|
+
key = args[0]
|
47
|
+
default = args[1]
|
48
|
+
override = args[2]
|
49
|
+
|
50
|
+
return [key, default, override]
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
module_function
|
55
|
+
|
56
|
+
def hiera
|
57
|
+
@hiera ||= Hiera.new(:config => hiera_config)
|
58
|
+
end
|
59
|
+
|
60
|
+
def hiera_config
|
61
|
+
config = {}
|
62
|
+
|
63
|
+
if config_file = hiera_config_file
|
64
|
+
config = Hiera::Config.load(config_file)
|
65
|
+
end
|
66
|
+
|
67
|
+
config[:logger] = 'puppet'
|
68
|
+
config
|
69
|
+
end
|
70
|
+
|
71
|
+
def hiera_config_file
|
72
|
+
config_file = nil
|
73
|
+
|
74
|
+
if Puppet.settings[:hiera_config].is_a?(String)
|
75
|
+
expanded_config_file = File.expand_path(Puppet.settings[:hiera_config])
|
76
|
+
if File.exist?(expanded_config_file)
|
77
|
+
config_file = expanded_config_file
|
78
|
+
end
|
79
|
+
elsif Puppet.settings[:confdir].is_a?(String)
|
80
|
+
expanded_config_file = File.expand_path(File.join(Puppet.settings[:confdir], '/hiera.yaml'))
|
81
|
+
if File.exist?(expanded_config_file)
|
82
|
+
config_file = expanded_config_file
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
config_file
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
@@ -1,45 +1,8 @@
|
|
1
1
|
module Puppet::Parser::Functions
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
# where as calling from templates should work like this:
|
8
|
-
# scope.function_lookup("foo", "bar")
|
9
|
-
#
|
10
|
-
# Therefore, declare this function with args '*args' to accept any number
|
11
|
-
# of arguments and deal with puppet's special calling mechanism now:
|
12
|
-
if args[0].is_a?(Array)
|
13
|
-
args = args[0]
|
14
|
-
end
|
15
|
-
|
16
|
-
key = args[0]
|
17
|
-
default = args[1]
|
18
|
-
override = args[2]
|
19
|
-
|
20
|
-
configfile = File.join([File.dirname(Puppet.settings[:config]), "hiera.yaml"])
|
21
|
-
|
22
|
-
raise(Puppet::ParseError, "Hiera config file #{configfile} not readable") unless File.exist?(configfile)
|
23
|
-
raise(Puppet::ParseError, "You need rubygems to use Hiera") unless Puppet.features.rubygems?
|
24
|
-
|
25
|
-
require 'hiera'
|
26
|
-
require 'hiera/scope'
|
27
|
-
|
28
|
-
config = YAML.load_file(configfile)
|
29
|
-
config[:logger] = "puppet"
|
30
|
-
|
31
|
-
hiera = Hiera.new(:config => config)
|
32
|
-
|
33
|
-
if self.respond_to?("[]")
|
34
|
-
hiera_scope = self
|
35
|
-
else
|
36
|
-
hiera_scope = Hiera::Scope.new(self)
|
37
|
-
end
|
38
|
-
|
39
|
-
answer = hiera.lookup(key, default, hiera_scope, override, :priority)
|
40
|
-
|
41
|
-
raise(Puppet::ParseError, "Could not find data item #{key} in any Hiera data file and no default supplied") if answer.nil?
|
42
|
-
|
43
|
-
return answer
|
44
|
-
end
|
2
|
+
newfunction(:hiera, :type => :rvalue) do |*args|
|
3
|
+
require 'hiera_puppet'
|
4
|
+
key, default, override = HieraPuppet.parse_args(args)
|
5
|
+
HieraPuppet.lookup(key, default, self, override, :priority)
|
6
|
+
end
|
45
7
|
end
|
8
|
+
|