hieracles 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Dependency Status](https://img.shields.io/gemnasium/Gandi/hieracles.svg)](https://gemnasium.com/Gandi/hieracles)
|
9
9
|
[![Code Climate](https://img.shields.io/codeclimate/github/Gandi/hieracles.svg)](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
|