hieracles 0.1.5 → 0.1.6
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -2
- data/README.md +34 -9
- data/hc.1 +5 -2
- data/hieracles.gemspec +2 -0
- data/lib/hieracles/config.rb +6 -2
- data/lib/hieracles/formats/console.rb +2 -2
- data/lib/hieracles/formats/csv.rb +2 -2
- data/lib/hieracles/formats/plain.rb +2 -2
- data/lib/hieracles/formats/yaml.rb +6 -1
- data/lib/hieracles/hiera.rb +9 -0
- data/lib/hieracles/interpolate.rb +31 -10
- data/lib/hieracles/node.rb +16 -7
- data/lib/hieracles/utils.rb +2 -2
- data/spec/files/params/farm/dev.yaml +8 -0
- data/spec/files/params/nodes/server.example.com.yaml +3 -0
- data/spec/lib/formats/console_spec.rb +2 -2
- data/spec/lib/formats/csv_spec.rb +2 -2
- data/spec/lib/formats/plain_spec.rb +2 -2
- data/spec/lib/formats/yaml_spec.rb +41 -4
- data/spec/lib/node_spec.rb +295 -98
- data/spec/lib/optparse_spec.rb +20 -2
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9b3915635847cd54b684b61feca924b9d11df20
|
4
|
+
data.tar.gz: 52c52b2b41f67079a635e8b092727c8478841ba7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f84fcf5cf3c49774c8fb7f6b6a025674c6e2b11173b65e66e75fa2bf0994274f9a8c096d5a7b5d5a7f8741d90193dc0394ec9852392aae7362d0a2a7a9effd4
|
7
|
+
data.tar.gz: 0ccd90fa9677651c2a75eb05eb427155321d18961594959d11eec87523353dfce36fafc697651dc3c0af18409e64c2ce3993f81676ab5d6c97ce3dd44770c6fe
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
Hieracles Changelog
|
2
2
|
=======================
|
3
3
|
|
4
|
+
### 0.1.6 - 2015-11-18
|
5
|
+
- add dependency on `deep-merge` gem like hiera does
|
6
|
+
- take in account the `merge_behavior` in hiera file
|
7
|
+
- make possible to use `%{::variables}` from puppet scope
|
8
|
+
but this is a temporary implementation,
|
9
|
+
only works for top level variables
|
10
|
+
|
4
11
|
### 0.1.5 - 2015-11-15
|
5
12
|
- add `interactive` new option `-i` for having
|
6
|
-
CLI user
|
13
|
+
CLI user prompted to fill up missing scope vars
|
7
14
|
- implement interpolation adapted from the code of hiera
|
8
15
|
- fixed the single option parsing for `-i`
|
9
16
|
|
@@ -27,7 +34,7 @@ Hieracles Changelog
|
|
27
34
|
- display full local path in params output
|
28
35
|
- add an option to display version
|
29
36
|
- fix yaml output for true and false cases
|
30
|
-
- added a simple filter
|
37
|
+
- added a simple filter feature for yaml format,
|
31
38
|
but it only matches like a 'start_with'
|
32
39
|
|
33
40
|
### 0.0.6 - 2015-09-21
|
data/README.md
CHANGED
@@ -8,12 +8,16 @@ Hieracles
|
|
8
8
|
[](https://gemnasium.com/Gandi/hieracles)
|
9
9
|
[](https://codeclimate.com/github/Gandi/hieracles)
|
10
10
|
|
11
|
-
Hieracles is a command-line tool for analysis and deep examination of [Hiera][hiera]
|
11
|
+
Hieracles is a command-line tool for analysis and deep examination of [Hiera][hiera] parameters in a [Puppet][puppet] setup. It can be used to quickly visualize, from a local puppet (typically on a developers environment), all the Hiera params related to a specific node.
|
12
|
+
|
13
|
+
It's used internally at [Gandi][gandi] and its first incarnation is strongly tied to Gandi puppet architecture. But Hieracles tends to become, in time, a generic Hiera overlay visualization tool.
|
14
|
+
|
15
|
+
Have a look at the [Changelog](CHANGELOG.md) for details about the evolution.
|
12
16
|
|
13
17
|
Prerequisite
|
14
18
|
---------------
|
15
19
|
|
16
|
-
There are many ways to setup puppet and use
|
20
|
+
There are many ways to setup puppet and use Hiera. This tool is designed to match a certain kind of setup, including:
|
17
21
|
|
18
22
|
- an [external node classifier (ENC)][enc]
|
19
23
|
- a yaml hiera datastore
|
@@ -139,17 +143,38 @@ Otherwise
|
|
139
143
|
|
140
144
|
Debian packaging
|
141
145
|
--------------------
|
142
|
-
On a Jessie
|
143
146
|
|
144
|
-
|
147
|
+
A debian/ dir is included you can just use `sbuild` in here and it will build the .deb.
|
145
148
|
|
146
|
-
|
149
|
+
For new releases:
|
147
150
|
|
148
|
-
|
151
|
+
- update the debian/changelog file
|
152
|
+
|
153
|
+
FreeBSD packaging
|
154
|
+
--------------------
|
149
155
|
|
150
|
-
|
156
|
+
For new releases:
|
157
|
+
|
158
|
+
- update the Makefile with new version number
|
159
|
+
- in a FreeBSD jail or machine:
|
160
|
+
```
|
161
|
+
cd hieracles
|
162
|
+
git pull
|
163
|
+
cd ports/
|
164
|
+
make makesum
|
165
|
+
# test the stuff, get that there is no warning or what
|
166
|
+
portlint
|
167
|
+
make stage
|
168
|
+
make check-orphans
|
169
|
+
make package
|
170
|
+
make install
|
171
|
+
make deinstall
|
172
|
+
make clean
|
173
|
+
cd ..
|
174
|
+
shar `find rubygem-hieracles` > rubygem-hieracles.shar
|
175
|
+
```
|
176
|
+
- on https://bugs.freebsd.org submit the new version
|
151
177
|
|
152
|
-
dpkg -i hieracles_0.0.6-1_all.deb
|
153
178
|
|
154
179
|
Todo
|
155
180
|
--------------
|
@@ -166,7 +191,7 @@ Todo
|
|
166
191
|
|
167
192
|
Authors
|
168
193
|
-----------
|
169
|
-
Hieracles original code is
|
194
|
+
Hieracles original code is written by [@mose](https://github.com/mose).
|
170
195
|
|
171
196
|
License
|
172
197
|
-----------
|
data/hc.1
CHANGED
@@ -13,8 +13,11 @@ hc \- Command tool for Hieracles
|
|
13
13
|
.SH DESCRIPTION
|
14
14
|
.PP
|
15
15
|
Hieracles is a command-line tool for analysis and deep examination
|
16
|
-
of
|
17
|
-
|
16
|
+
of Hiera parameters in a Puppet setup. It can be used to quickly
|
17
|
+
visualize, from a local puppet (typically on a developers
|
18
|
+
environment), all the Hiera params related to a specific node.
|
19
|
+
.PP
|
20
|
+
It's used internally at Gandi and its first incarnation is strongly
|
18
21
|
tied to Gandi puppet architecture. But Hieracles tends to become, in
|
19
22
|
time, a generic Hiera overlay visualization tool.
|
20
23
|
.PP
|
data/hieracles.gemspec
CHANGED
@@ -77,6 +77,8 @@ Gem::Specification.new do |spec|
|
|
77
77
|
spec.test_files = spec.files.grep(%r{^spec/})
|
78
78
|
spec.require_paths = ["lib"]
|
79
79
|
|
80
|
+
spec.add_dependency 'deep_merge'
|
81
|
+
|
80
82
|
spec.add_development_dependency "bundler", "~> 1.7"
|
81
83
|
spec.add_development_dependency "rake", "~> 10.0"
|
82
84
|
spec.add_development_dependency 'rspec', "~> 3.0"
|
data/lib/hieracles/config.rb
CHANGED
@@ -15,8 +15,7 @@ module Hieracles
|
|
15
15
|
def load(options)
|
16
16
|
@optionfile = options[:config] || defaultconfig
|
17
17
|
@extraparams = extract_params(options[:params])
|
18
|
-
|
19
|
-
values = YAML.load_file(@optionfile)
|
18
|
+
values = get_config(@optionfile)
|
20
19
|
@server = values['server']
|
21
20
|
@classpath = values['classpath']
|
22
21
|
@modulepath = values['modulepath'] || 'modules'
|
@@ -30,6 +29,11 @@ module Hieracles
|
|
30
29
|
@interactive = options[:interactive] || values['interactive']
|
31
30
|
end
|
32
31
|
|
32
|
+
def get_config(file)
|
33
|
+
initconfig(file) unless File.exist? file
|
34
|
+
values = YAML.load_file(file)
|
35
|
+
end
|
36
|
+
|
33
37
|
def initconfig(file)
|
34
38
|
FileUtils.mkdir_p(File.dirname(file))
|
35
39
|
File.open(file, 'w') do |f|
|
@@ -52,7 +52,7 @@ module Hieracles
|
|
52
52
|
def build_params_line(key, value, filter)
|
53
53
|
output = ''
|
54
54
|
if !filter || Regexp.new(filter).match(key)
|
55
|
-
first = value.
|
55
|
+
first = value.pop
|
56
56
|
filecolor_index = @colors[first[:file]]
|
57
57
|
filecolor = COLORS[filecolor_index]
|
58
58
|
output << format("#{filecolor} #{COLORS[5]} %s\n",
|
@@ -61,7 +61,7 @@ module Hieracles
|
|
61
61
|
first[:value].to_s.gsub('%', '%%')
|
62
62
|
)
|
63
63
|
while value.count > 0
|
64
|
-
overriden = value.
|
64
|
+
overriden = value.pop
|
65
65
|
filecolor_index = @colors[overriden[:file]]
|
66
66
|
output << format(" #{COLORS[8]}\n",
|
67
67
|
"[#{filecolor_index}] #{key} #{overriden[:value]}"
|
@@ -28,11 +28,11 @@ module Hieracles
|
|
28
28
|
def build_params_line(key, value, filter)
|
29
29
|
output = ''
|
30
30
|
if !filter || Regexp.new(filter).match(key)
|
31
|
-
first = value.
|
31
|
+
first = value.pop
|
32
32
|
output << make_csv(in_what_file(first[:file]) +
|
33
33
|
[key, first[:value].to_s, '0'])
|
34
34
|
while value.count > 0
|
35
|
-
overriden = value.
|
35
|
+
overriden = value.pop
|
36
36
|
output << make_csv(in_what_file(overriden[:file]) +
|
37
37
|
[key, overriden[:value].to_s, '1'])
|
38
38
|
end
|
@@ -39,11 +39,11 @@ module Hieracles
|
|
39
39
|
def build_params_line(key, value, filter)
|
40
40
|
output = ''
|
41
41
|
if !filter || Regexp.new(filter).match(key)
|
42
|
-
first = value.
|
42
|
+
first = value.pop
|
43
43
|
filecolor_index = @index[first[:file]]
|
44
44
|
output << "[#{filecolor_index}] #{key} #{first[:value]}\n"
|
45
45
|
while value.count > 0
|
46
|
-
overriden = value.
|
46
|
+
overriden = value.pop
|
47
47
|
filecolor_index = @index[overriden[:file]]
|
48
48
|
output << " [#{filecolor_index}] #{key} #{overriden[:value]}\n"
|
49
49
|
end
|
@@ -91,7 +91,12 @@ module Hieracles
|
|
91
91
|
def added(output, key, leaf, params)
|
92
92
|
output += leaf.to_s
|
93
93
|
if params["#{key.join('.')}"]
|
94
|
-
|
94
|
+
params["#{key.join('.')}"].each do |k|
|
95
|
+
if k[:value].to_s == leaf.to_s
|
96
|
+
output += " # " + k[:file]
|
97
|
+
break
|
98
|
+
end
|
99
|
+
end
|
95
100
|
end
|
96
101
|
output
|
97
102
|
end
|
data/lib/hieracles/hiera.rb
CHANGED
@@ -26,5 +26,14 @@ module Hieracles
|
|
26
26
|
hierarchy.join(',').scan(/%\{(?:::)?([^\}]*)\}/).flatten.uniq
|
27
27
|
end
|
28
28
|
|
29
|
+
def merge_behavior
|
30
|
+
case @loaded[:merge_behavior]
|
31
|
+
when :deep,'deep',:deeper,'deeper'
|
32
|
+
@loaded[:merge_behavior].to_sym
|
33
|
+
else
|
34
|
+
:native
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
29
38
|
end
|
30
39
|
end
|
@@ -2,22 +2,43 @@ module Hieracles
|
|
2
2
|
module Interpolate
|
3
3
|
|
4
4
|
def parse(data, values, interactive = false)
|
5
|
-
data.gsub(/%\{(?:(scope|hiera|literal|alias)
|
5
|
+
data.gsub(/%\{(?:(scope|hiera|literal|alias)\(['"])?(?:::)?([^\}"']*)(?:["']\))?\}/) do |match|
|
6
6
|
if interactive && !values[$2.to_sym]
|
7
|
-
|
8
|
-
|
9
|
-
puts "Is it missing in your ENC source?"
|
10
|
-
puts "Maybe you should define a default value for that scope variable in your config file?"
|
11
|
-
puts "Do you want to provide a temmporary value? [input value]"
|
12
|
-
print "#{$2} = "
|
13
|
-
val = $stdin.gets.chomp
|
14
|
-
values[$2.to_sym] = val
|
15
|
-
val
|
7
|
+
values[$2.to_sym] = ask_about($2)
|
8
|
+
values[$2.to_sym]
|
16
9
|
else
|
17
10
|
values[$2.to_sym]
|
18
11
|
end
|
19
12
|
end
|
20
13
|
end
|
21
14
|
|
15
|
+
def ask_about(var)
|
16
|
+
@@output.puts
|
17
|
+
@@output.puts "'#{var}' is not defined."
|
18
|
+
@@output.puts "Is it missing in your ENC source?"
|
19
|
+
@@output.puts "Maybe you should define a default value for that scope variable in your config file?"
|
20
|
+
@@output.puts "Do you want to provide a temmporary value? [input value]"
|
21
|
+
@@output.print "#{var} = "
|
22
|
+
@@input.gets.chomp
|
23
|
+
end
|
24
|
+
|
25
|
+
# makes possible to set input and output
|
26
|
+
def setio(input, output)
|
27
|
+
@@input = input
|
28
|
+
@@output = output
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# defaults to STDIN
|
34
|
+
def input
|
35
|
+
@@input ||= STDIN
|
36
|
+
end
|
37
|
+
|
38
|
+
# defaults to STDOUT
|
39
|
+
def output
|
40
|
+
@@output ||= STDOUT
|
41
|
+
end
|
42
|
+
|
22
43
|
end
|
23
44
|
end
|
data/lib/hieracles/node.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "net/http"
|
2
2
|
require "uri"
|
3
3
|
require "yaml"
|
4
|
+
require 'deep_merge'
|
4
5
|
|
5
6
|
module Hieracles
|
6
7
|
class Node
|
@@ -47,7 +48,7 @@ module Hieracles
|
|
47
48
|
|
48
49
|
def params(without_common = true)
|
49
50
|
params = {}
|
50
|
-
files(without_common).each do |f|
|
51
|
+
files(without_common).reverse.each do |f|
|
51
52
|
data = YAML.load_file(File.join(Config.basepath, f))
|
52
53
|
if data
|
53
54
|
s = to_shallow_hash(data)
|
@@ -63,12 +64,9 @@ module Hieracles
|
|
63
64
|
|
64
65
|
def params_tree(without_common = true)
|
65
66
|
params = {}
|
66
|
-
paths(without_common).each do |f|
|
67
|
-
data = YAML.load_file(f)
|
68
|
-
|
69
|
-
# data needs interpolation
|
70
|
-
deep_merge!(params, data)
|
71
|
-
end
|
67
|
+
paths(without_common).reverse.each do |f|
|
68
|
+
data = YAML.load_file(f) || {}
|
69
|
+
merge_trees params, data
|
72
70
|
end
|
73
71
|
deep_sort(params)
|
74
72
|
end
|
@@ -116,5 +114,16 @@ module Hieracles
|
|
116
114
|
modules
|
117
115
|
end
|
118
116
|
|
117
|
+
def merge_trees(left, right)
|
118
|
+
case @hiera.merge_behavior
|
119
|
+
when :deeper
|
120
|
+
left.deep_merge!(right)
|
121
|
+
when :deep
|
122
|
+
left.deep_merge(right)
|
123
|
+
else # Native and undefined
|
124
|
+
local_merge!(left, right)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
119
128
|
end
|
120
129
|
end
|
data/lib/hieracles/utils.rb
CHANGED
@@ -19,12 +19,12 @@ module Hieracles
|
|
19
19
|
keys = key.to_s.split('.').reverse
|
20
20
|
leaf_key = keys.shift
|
21
21
|
key_hash = keys.reduce(leaf_key.to_sym => value) { |h, k| { k.to_sym => h } }
|
22
|
-
|
22
|
+
local_merge!(a, key_hash)
|
23
23
|
a
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
27
|
+
def local_merge!(hash1, hash2)
|
28
28
|
merger = proc { |key, v1, v2| v1.is_a?(Hash) && v2.is_a?(Hash) ? v1.merge(v2, &merger) : v2 }
|
29
29
|
hash1.merge!(hash2, &merger)
|
30
30
|
end
|
@@ -54,8 +54,8 @@ describe Hieracles::Formats::Console do
|
|
54
54
|
|
55
55
|
describe ".build_params_line" do
|
56
56
|
let(:expected) {
|
57
|
-
"\e[
|
58
|
-
" \e[97m[
|
57
|
+
"\e[32m[1]\e[0m \e[36mparams.this.var\e[0m value2\n"+
|
58
|
+
" \e[97m[0] params.this.var value1\e[0m\n"
|
59
59
|
}
|
60
60
|
let(:params) {
|
61
61
|
[
|
@@ -51,8 +51,8 @@ describe Hieracles::Formats::Csv do
|
|
51
51
|
|
52
52
|
describe ".build_params_line" do
|
53
53
|
let(:expected) {
|
54
|
-
"1;
|
55
|
-
"0;
|
54
|
+
"0;1;params.this.var;value2;0\n"+
|
55
|
+
"1;0;params.this.var;value1;1\n"
|
56
56
|
}
|
57
57
|
let(:params) {
|
58
58
|
[
|
@@ -54,8 +54,8 @@ describe Hieracles::Formats::Plain do
|
|
54
54
|
|
55
55
|
describe ".build_params_line" do
|
56
56
|
let(:expected) {
|
57
|
-
"[
|
58
|
-
" [
|
57
|
+
"[1] params.this.var value2\n"+
|
58
|
+
" [0] params.this.var value1\n"
|
59
59
|
}
|
60
60
|
let(:params) {
|
61
61
|
[
|
@@ -127,7 +127,7 @@ describe Hieracles::Formats::Yaml do
|
|
127
127
|
{
|
128
128
|
'key' => [{
|
129
129
|
file: 'what/file',
|
130
|
-
value: '
|
130
|
+
value: 'true'
|
131
131
|
}]
|
132
132
|
}
|
133
133
|
}
|
@@ -144,7 +144,7 @@ describe Hieracles::Formats::Yaml do
|
|
144
144
|
{
|
145
145
|
'key' => [{
|
146
146
|
file: 'what/file',
|
147
|
-
value: '
|
147
|
+
value: 'false'
|
148
148
|
}]
|
149
149
|
}
|
150
150
|
}
|
@@ -161,7 +161,7 @@ describe Hieracles::Formats::Yaml do
|
|
161
161
|
{
|
162
162
|
'key' => [{
|
163
163
|
file: 'what/file',
|
164
|
-
value: '
|
164
|
+
value: '3'
|
165
165
|
}]
|
166
166
|
}
|
167
167
|
}
|
@@ -178,7 +178,7 @@ describe Hieracles::Formats::Yaml do
|
|
178
178
|
{
|
179
179
|
'key' => [{
|
180
180
|
file: 'what/file',
|
181
|
-
value: '
|
181
|
+
value: '0.3'
|
182
182
|
}]
|
183
183
|
}
|
184
184
|
}
|
@@ -308,6 +308,43 @@ describe Hieracles::Formats::Yaml do
|
|
308
308
|
}
|
309
309
|
it { expect(yaml_format.mergetree('', [], input, params)).to eq expected }
|
310
310
|
end
|
311
|
+
context "with a 3-levels double string key-value and override" do
|
312
|
+
let(:params) {
|
313
|
+
{
|
314
|
+
'key.sublevel.subsublevel' => [{
|
315
|
+
file: 'what/file',
|
316
|
+
value: 'value'
|
317
|
+
}],
|
318
|
+
'key2.sublevel' => [
|
319
|
+
{
|
320
|
+
file: 'what/file2',
|
321
|
+
value: 'value'
|
322
|
+
},
|
323
|
+
{
|
324
|
+
file: 'what/file1',
|
325
|
+
value: 'value2'
|
326
|
+
}
|
327
|
+
]
|
328
|
+
}
|
329
|
+
}
|
330
|
+
let(:input) {
|
331
|
+
{
|
332
|
+
'key' => {
|
333
|
+
'sublevel' => {
|
334
|
+
'subsublevel' => 'value'
|
335
|
+
}
|
336
|
+
},
|
337
|
+
'key2' => {
|
338
|
+
'sublevel' => 'value2'
|
339
|
+
}
|
340
|
+
}
|
341
|
+
}
|
342
|
+
let(:expected) {
|
343
|
+
"\nkey: \n sublevel: \n subsublevel: value # what/file" +
|
344
|
+
"\nkey2: \n sublevel: value2 # what/file1"
|
345
|
+
}
|
346
|
+
it { expect(yaml_format.mergetree('', [], input, params)).to eq expected }
|
347
|
+
end
|
311
348
|
end
|
312
349
|
|
313
350
|
end
|
data/spec/lib/node_spec.rb
CHANGED
@@ -1,58 +1,208 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Hieracles::Node do
|
4
|
-
|
5
|
-
{
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
context "with native merge" do
|
5
|
+
let(:options) {
|
6
|
+
{
|
7
|
+
config: 'spec/files/config.yml',
|
8
|
+
hierafile: 'hiera.yaml',
|
9
|
+
encpath: 'enc',
|
10
|
+
basepath: 'spec/files'
|
11
|
+
}
|
10
12
|
}
|
11
|
-
}
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
}
|
18
|
-
let(:node) { Hieracles::Node.new 'server.example.com', extraoptions }
|
19
|
-
let(:expected) {
|
20
|
-
{
|
21
|
-
classes: ['dev'],
|
22
|
-
fqdn: 'server.example.com',
|
23
|
-
country: 'fr',
|
24
|
-
datacenter: 'equinix',
|
25
|
-
farm: 'dev',
|
26
|
-
key1: 'value1',
|
27
|
-
key2: 'value2'
|
14
|
+
context "when extra parameters are specified" do
|
15
|
+
describe '.new' do
|
16
|
+
let(:extraoptions) {
|
17
|
+
options.merge({ params: 'key1=value1;key2=value2' })
|
28
18
|
}
|
29
|
-
|
30
|
-
|
31
|
-
|
19
|
+
let(:node) { Hieracles::Node.new 'server.example.com', extraoptions }
|
20
|
+
let(:expected) {
|
21
|
+
{
|
22
|
+
classes: ['dev'],
|
23
|
+
fqdn: 'server.example.com',
|
24
|
+
country: 'fr',
|
25
|
+
datacenter: 'equinix',
|
26
|
+
farm: 'dev',
|
27
|
+
key1: 'value1',
|
28
|
+
key2: 'value2'
|
29
|
+
}
|
30
|
+
}
|
31
|
+
it { expect(node).to be_a Hieracles::Node }
|
32
|
+
it { expect(node.hiera_params).to eq expected }
|
33
|
+
end
|
32
34
|
end
|
33
|
-
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
context "when parameters are not valid" do
|
37
|
+
let(:node) { Hieracles::Node.new 'server_not_there.example.com', options }
|
38
|
+
it { expect{ node }.to raise_error(RuntimeError) }
|
39
|
+
end
|
39
40
|
|
40
|
-
|
41
|
-
|
41
|
+
context "when parameters are valid" do
|
42
|
+
let(:node) { Hieracles::Node.new 'server.example.com', options }
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
describe '.new' do
|
45
|
+
let(:expected) {
|
46
|
+
{
|
47
|
+
classes: ['dev'],
|
48
|
+
fqdn: 'server.example.com',
|
49
|
+
country: 'fr',
|
50
|
+
datacenter: 'equinix',
|
51
|
+
farm: 'dev'
|
52
|
+
}
|
53
|
+
}
|
54
|
+
it { expect(node).to be_a Hieracles::Node }
|
55
|
+
it { expect(node.hiera_params).to eq expected }
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '.files' do
|
59
|
+
let(:expected) {
|
60
|
+
[
|
61
|
+
'params/nodes/server.example.com.yaml',
|
62
|
+
'params/farm/dev.yaml'
|
63
|
+
]
|
64
|
+
}
|
65
|
+
it { expect(node.files).to eq expected }
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '.paths' do
|
69
|
+
let(:expected) {
|
70
|
+
[
|
71
|
+
File.join(node.hiera.datapath, 'nodes/server.example.com.yaml'),
|
72
|
+
File.join(node.hiera.datapath, 'farm/dev.yaml')
|
73
|
+
]
|
74
|
+
}
|
75
|
+
it { expect(node.paths).to eq expected }
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '.params' do
|
79
|
+
let(:expected) {
|
80
|
+
[
|
81
|
+
[ "another.more_sublevel",
|
82
|
+
[{
|
83
|
+
value: "something",
|
84
|
+
file: 'params/farm/dev.yaml'
|
85
|
+
}]
|
86
|
+
],
|
87
|
+
[ "another.sublevel.array",
|
88
|
+
[
|
89
|
+
{
|
90
|
+
value: ["one", "two", "three"],
|
91
|
+
file: 'params/farm/dev.yaml'
|
92
|
+
},
|
93
|
+
{
|
94
|
+
value: ["four", "five"],
|
95
|
+
file: 'params/nodes/server.example.com.yaml'
|
96
|
+
}
|
97
|
+
]
|
98
|
+
],
|
99
|
+
[ "another.sublevel.thing",
|
100
|
+
[{
|
101
|
+
value: "always",
|
102
|
+
file: 'params/nodes/server.example.com.yaml'
|
103
|
+
}]
|
104
|
+
],
|
105
|
+
[ "common_param.subparam",
|
106
|
+
[{
|
107
|
+
value: "overriden",
|
108
|
+
file: 'params/nodes/server.example.com.yaml'
|
109
|
+
}]
|
110
|
+
],
|
111
|
+
[ "somefarmparam",
|
112
|
+
[{
|
113
|
+
value: false,
|
114
|
+
file: 'params/farm/dev.yaml'
|
115
|
+
}]
|
116
|
+
]
|
117
|
+
]
|
118
|
+
}
|
119
|
+
it { expect(node.params).to eq expected }
|
120
|
+
end
|
121
|
+
|
122
|
+
describe '.params_tree' do
|
123
|
+
let(:expected) {
|
124
|
+
{
|
125
|
+
"another" => {
|
126
|
+
"more_sublevel" => "something",
|
127
|
+
"sublevel" => {
|
128
|
+
"array" => ["five", "four"],
|
129
|
+
"thing" => "always"
|
130
|
+
}
|
131
|
+
},
|
132
|
+
"common_param" => {
|
133
|
+
"subparam" => "overriden"
|
134
|
+
},
|
135
|
+
"somefarmparam" => false
|
136
|
+
}
|
137
|
+
}
|
138
|
+
it { expect(node.params_tree).to eq expected }
|
139
|
+
end
|
140
|
+
|
141
|
+
describe '.modules' do
|
142
|
+
context "no unfound modules" do
|
143
|
+
let(:expected) {
|
144
|
+
{
|
145
|
+
"fake_module" => "modules/fake_module",
|
146
|
+
"fake_module2" => "modules/fake_module2",
|
147
|
+
"fake_module3" => "modules/fake_module3"
|
148
|
+
}
|
149
|
+
}
|
150
|
+
it { expect(node.modules).to eq expected }
|
151
|
+
end
|
152
|
+
context "one unfound modules" do
|
153
|
+
let(:node) { Hieracles::Node.new 'server2.example.com', options }
|
154
|
+
let(:expected) {
|
155
|
+
{
|
156
|
+
"fake_module" => "modules/fake_module",
|
157
|
+
"fake_module2" => "modules/fake_module2",
|
158
|
+
"fake_module4" => nil
|
159
|
+
}
|
160
|
+
}
|
161
|
+
it { expect(node.modules).to eq expected }
|
162
|
+
end
|
163
|
+
context "no farm file found" do
|
164
|
+
let(:node) { Hieracles::Node.new 'server3.example.com', options }
|
165
|
+
it { expect { node.modules }.to raise_error(RuntimeError) }
|
166
|
+
end
|
167
|
+
context "multiple classes included" do
|
168
|
+
let(:node) { Hieracles::Node.new 'server4.example.com', options }
|
169
|
+
let(:expected) {
|
170
|
+
{
|
171
|
+
"fake_module" => "modules/fake_module",
|
172
|
+
"fake_module2" => "modules/fake_module2",
|
173
|
+
"fake_module4" => nil,
|
174
|
+
"faux_module1" => "modules/faux_module1",
|
175
|
+
"faux_module2" => "modules/faux_module2"
|
176
|
+
}
|
177
|
+
}
|
178
|
+
it { expect(node.modules).to eq expected }
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe '.info' do
|
183
|
+
let(:expected) { {
|
46
184
|
classes: ['dev'],
|
47
185
|
fqdn: 'server.example.com',
|
48
|
-
country: 'fr',
|
49
186
|
datacenter: 'equinix',
|
187
|
+
country: 'fr',
|
50
188
|
farm: 'dev'
|
51
|
-
}
|
52
|
-
|
53
|
-
|
54
|
-
|
189
|
+
} }
|
190
|
+
it { expect(node.info).to eq expected }
|
191
|
+
end
|
192
|
+
|
55
193
|
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context "when parameters include double-column variables" do
|
197
|
+
let(:options) {
|
198
|
+
{
|
199
|
+
config: 'spec/files/config.yml',
|
200
|
+
hierafile: 'hiera_columns.yaml',
|
201
|
+
encpath: 'enc',
|
202
|
+
basepath: 'spec/files'
|
203
|
+
}
|
204
|
+
}
|
205
|
+
let(:node) { Hieracles::Node.new 'server.example.com', options }
|
56
206
|
|
57
207
|
describe '.files' do
|
58
208
|
let(:expected) {
|
@@ -63,20 +213,41 @@ describe Hieracles::Node do
|
|
63
213
|
}
|
64
214
|
it { expect(node.files).to eq expected }
|
65
215
|
end
|
216
|
+
end
|
66
217
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
218
|
+
|
219
|
+
context "with deep merge" do
|
220
|
+
let(:options) {
|
221
|
+
{
|
222
|
+
config: 'spec/files/config.yml',
|
223
|
+
hierafile: 'hiera_deep.yaml',
|
224
|
+
encpath: 'enc',
|
225
|
+
basepath: 'spec/files'
|
73
226
|
}
|
74
|
-
|
75
|
-
|
227
|
+
}
|
228
|
+
let(:node) { Hieracles::Node.new 'server.example.com', options }
|
76
229
|
|
77
230
|
describe '.params' do
|
78
231
|
let(:expected) {
|
79
232
|
[
|
233
|
+
[ "another.more_sublevel",
|
234
|
+
[{
|
235
|
+
value: "something",
|
236
|
+
file: 'params/farm/dev.yaml'
|
237
|
+
}]
|
238
|
+
],
|
239
|
+
[ "another.sublevel.array",
|
240
|
+
[
|
241
|
+
{
|
242
|
+
value: ["one", "two", "three"],
|
243
|
+
file: 'params/farm/dev.yaml'
|
244
|
+
},
|
245
|
+
{
|
246
|
+
value: ["four", "five"],
|
247
|
+
file: 'params/nodes/server.example.com.yaml'
|
248
|
+
}
|
249
|
+
]
|
250
|
+
],
|
80
251
|
[ "another.sublevel.thing",
|
81
252
|
[{
|
82
253
|
value: "always",
|
@@ -103,9 +274,11 @@ describe Hieracles::Node do
|
|
103
274
|
describe '.params_tree' do
|
104
275
|
let(:expected) {
|
105
276
|
{
|
106
|
-
"another" => {
|
277
|
+
"another" => {
|
278
|
+
"more_sublevel" => "something",
|
107
279
|
"sublevel" => {
|
108
|
-
"
|
280
|
+
"array" => ["five", "four", "one", "three", "two"],
|
281
|
+
"thing" => "always",
|
109
282
|
}
|
110
283
|
},
|
111
284
|
"common_param" => {
|
@@ -117,57 +290,81 @@ describe Hieracles::Node do
|
|
117
290
|
it { expect(node.params_tree).to eq expected }
|
118
291
|
end
|
119
292
|
|
293
|
+
end
|
120
294
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
295
|
+
|
296
|
+
context "with deeper merge" do
|
297
|
+
let(:options) {
|
298
|
+
{
|
299
|
+
config: 'spec/files/config.yml',
|
300
|
+
hierafile: 'hiera_deeper.yaml',
|
301
|
+
encpath: 'enc',
|
302
|
+
basepath: 'spec/files'
|
303
|
+
}
|
304
|
+
}
|
305
|
+
let(:node) { Hieracles::Node.new 'server.example.com', options }
|
306
|
+
|
307
|
+
describe '.params' do
|
308
|
+
let(:expected) {
|
309
|
+
[
|
310
|
+
[ "another.more_sublevel",
|
311
|
+
[{
|
312
|
+
value: "something",
|
313
|
+
file: 'params/farm/dev.yaml'
|
314
|
+
}]
|
315
|
+
],
|
316
|
+
[ "another.sublevel.array",
|
317
|
+
[
|
318
|
+
{
|
319
|
+
value: ["one", "two", "three"],
|
320
|
+
file: 'params/farm/dev.yaml'
|
321
|
+
},
|
322
|
+
{
|
323
|
+
value: ["four", "five"],
|
324
|
+
file: 'params/nodes/server.example.com.yaml'
|
325
|
+
}
|
326
|
+
]
|
327
|
+
],
|
328
|
+
[ "another.sublevel.thing",
|
329
|
+
[{
|
330
|
+
value: "always",
|
331
|
+
file: 'params/nodes/server.example.com.yaml'
|
332
|
+
}]
|
333
|
+
],
|
334
|
+
[ "common_param.subparam",
|
335
|
+
[{
|
336
|
+
value: "overriden",
|
337
|
+
file: 'params/nodes/server.example.com.yaml'
|
338
|
+
}]
|
339
|
+
],
|
340
|
+
[ "somefarmparam",
|
341
|
+
[{
|
342
|
+
value: false,
|
343
|
+
file: 'params/farm/dev.yaml'
|
344
|
+
}]
|
345
|
+
]
|
346
|
+
]
|
347
|
+
}
|
348
|
+
it { expect(node.params).to eq expected }
|
160
349
|
end
|
161
350
|
|
162
|
-
describe '.
|
163
|
-
let(:expected) {
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
351
|
+
describe '.params_tree' do
|
352
|
+
let(:expected) {
|
353
|
+
{
|
354
|
+
"another" => {
|
355
|
+
"more_sublevel" => "something",
|
356
|
+
"sublevel" => {
|
357
|
+
"array" => ["five", "four", "one", "three", "two"],
|
358
|
+
"thing" => "always",
|
359
|
+
}
|
360
|
+
},
|
361
|
+
"common_param" => {
|
362
|
+
"subparam" => "overriden"
|
363
|
+
},
|
364
|
+
"somefarmparam" => false
|
365
|
+
}
|
366
|
+
}
|
367
|
+
it { expect(node.params_tree).to eq expected }
|
171
368
|
end
|
172
369
|
|
173
370
|
end
|
data/spec/lib/optparse_spec.rb
CHANGED
@@ -32,7 +32,7 @@ describe Hieracles::Optparse do
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
context 'with
|
35
|
+
context 'with funnily ordered arguments' do
|
36
36
|
let(:array) { ['arg1', '-u', 'path/to/config-file', 'arg2', '-f', 'thatformat'] }
|
37
37
|
let(:expected_payload) { ['arg1', 'arg2'] }
|
38
38
|
let(:expected_options) do
|
@@ -48,7 +48,7 @@ describe Hieracles::Optparse do
|
|
48
48
|
end
|
49
49
|
|
50
50
|
context 'with arguments in alternative syntax' do
|
51
|
-
let(:array) { ['arg1', 'arg2', '-config', 'path/to/config-file', '
|
51
|
+
let(:array) { ['arg1', 'arg2', '-config', 'path/to/config-file', '--format', 'thatformat'] }
|
52
52
|
let(:expected_payload) { ['arg1', 'arg2'] }
|
53
53
|
let(:expected_options) do
|
54
54
|
{ config: 'path/to/config-file', format: 'thatformat' }
|
@@ -61,5 +61,23 @@ describe Hieracles::Optparse do
|
|
61
61
|
expect(subject.options).to eq expected_options
|
62
62
|
end
|
63
63
|
end
|
64
|
+
|
65
|
+
|
66
|
+
context 'with arguments containing boolean element' do
|
67
|
+
let(:array) { ['arg1', 'arg2', '-i', '-format', 'thatformat'] }
|
68
|
+
let(:expected_payload) { ['arg1', 'arg2'] }
|
69
|
+
let(:expected_options) do
|
70
|
+
{ format: 'thatformat', interactive: true }
|
71
|
+
end
|
72
|
+
subject { Hieracles::Optparse.new array }
|
73
|
+
it "populates payload" do
|
74
|
+
expect(subject.payload).to eq expected_payload
|
75
|
+
end
|
76
|
+
it 'populates options' do
|
77
|
+
expect(subject.options).to eq expected_options
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
64
82
|
end
|
65
83
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hieracles
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mose
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-11-
|
11
|
+
date: 2015-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: deep_merge
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|