hieracles 0.0.1
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 +7 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +30 -0
- data/Rakefile +14 -0
- data/bin/hc +32 -0
- data/bin/nodeinfo +41 -0
- data/hieracles.gemspec +30 -0
- data/lib/hieracles.rb +15 -0
- data/lib/hieracles/config.rb +56 -0
- data/lib/hieracles/format.rb +58 -0
- data/lib/hieracles/formats/console.rb +84 -0
- data/lib/hieracles/formats/csv.rb +66 -0
- data/lib/hieracles/formats/plain.rb +61 -0
- data/lib/hieracles/formats/yaml.rb +36 -0
- data/lib/hieracles/help.rb +27 -0
- data/lib/hieracles/hiera.rb +27 -0
- data/lib/hieracles/node.rb +108 -0
- data/lib/hieracles/optparse.rb +63 -0
- data/lib/hieracles/utils.rb +59 -0
- data/spec/files/config.yml +5 -0
- data/spec/files/enc/server.example.com.yaml +7 -0
- data/spec/files/enc/server2.example.com.yaml +7 -0
- data/spec/files/enc/server3.example.com.yaml +7 -0
- data/spec/files/farm_modules/dev.pp +5 -0
- data/spec/files/farm_modules/dev2.pp +5 -0
- data/spec/files/hiera.yaml +16 -0
- data/spec/files/hiera_no_yamlbackend.yaml +16 -0
- data/spec/files/hiera_yamlbackend_notfound.yaml +16 -0
- data/spec/files/modules/fake_module/manifests/init.pp +3 -0
- data/spec/files/modules/fake_module2/manifests/init.pp +3 -0
- data/spec/files/modules/fake_module3/manifests/init.pp +3 -0
- data/spec/files/params/common/common.yml +2 -0
- data/spec/files/params/farm/dev.yaml +1 -0
- data/spec/files/params/nodes/server.example.com.yaml +5 -0
- data/spec/lib/config_spec.rb +63 -0
- data/spec/lib/format_spec.rb +91 -0
- data/spec/lib/formats/console_spec.rb +107 -0
- data/spec/lib/formats/csv_spec.rb +89 -0
- data/spec/lib/formats/plain_spec.rb +94 -0
- data/spec/lib/formats/yaml_spec.rb +80 -0
- data/spec/lib/help_spec.rb +8 -0
- data/spec/lib/hiera_spec.rb +111 -0
- data/spec/lib/node_spec.rb +158 -0
- data/spec/lib/optparse_spec.rb +65 -0
- data/spec/lib/utils_spec.rb +61 -0
- data/spec/spec_helper.rb +26 -0
- metadata +223 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b9af763f884a9153607dbc67b10cc0fcd0eb79c8
|
4
|
+
data.tar.gz: 0fc7b717a7a598c3a78245dd18761a11140629cd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 296005bd9070c34848c6f53cdb0e03a4e6b099cf2ac06bc97c5d543a8bf4a89cd40187e7cfd643cb0615867fb9be2d4f8e5618522f9bcb2cd498322d0c9d2281
|
7
|
+
data.tar.gz: 4f251c0dcd1143cffadfc09484af1eaf06af19d671b166d1b49d0b96d4e3ab80804bf20381a9af5b42384e4a79072610caed2e8a83c70ef0aed0b5d1502b28fd
|
data/.coveralls.yml
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
Hieracles Changelog
|
2
|
+
=======================
|
3
|
+
|
4
|
+
### 0.0.1 - 2015-09-12
|
5
|
+
- first alpha release
|
6
|
+
- added extensive testing using rspec
|
7
|
+
- add more config variables and parameters for fitting various environments
|
8
|
+
- initial transition to Github from internal v0.0.5 Gandi code.
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 gandi.net
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
Hieracles
|
2
|
+
================
|
3
|
+
|
4
|
+
[](https://travis-ci.org/Gandi/hieracles)
|
5
|
+
[](https://coveralls.io/r/Gandi/hieracles?branch=master)
|
6
|
+
[](https://gemnasium.com/Gandi/hieracles)
|
7
|
+
[](https://codeclimate.com/github/Gandi/hieracles)
|
8
|
+
|
9
|
+
Hieracles is a command-line tool for analysis and deep examination of [Hiera][hiera] paramaters in a [Puppet][puppet] setup. 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 visualisation tool.
|
10
|
+
|
11
|
+
Install
|
12
|
+
-----------
|
13
|
+
At this stage, it's to early to even think about installing anything. The internal code from Gandi is still in progress of transition towards total freedom.
|
14
|
+
|
15
|
+
Authors
|
16
|
+
-----------
|
17
|
+
Hieracles original code is writen by [@mose](https://github.com/mose).
|
18
|
+
|
19
|
+
License
|
20
|
+
-----------
|
21
|
+
Hieracles is available under MIT license. See [LICENSE](./LICENSE) file for more details
|
22
|
+
|
23
|
+
Copyright
|
24
|
+
------------
|
25
|
+
copyright (c) 2015 Gandi http://gandi.net
|
26
|
+
|
27
|
+
|
28
|
+
[puppet]: https://github.com/puppetlabs/puppet
|
29
|
+
[hiera]: https://github.com/puppetlabs/hiera
|
30
|
+
[gandi]: https://gandi.net
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
desc 'launch rspec tests'
|
7
|
+
task :spec do
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
9
|
+
t.rspec_opts = ['-c', '-f Fivemat', '-r ./spec/spec_helper.rb']
|
10
|
+
t.pattern = 'spec/lib/**/*_spec.rb'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
task default: :spec
|
data/bin/hc
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH << File.expand_path("../../lib", __FILE__)
|
4
|
+
|
5
|
+
require 'hieracles'
|
6
|
+
|
7
|
+
opt = Hieracles::Optparse.new(ARGV)
|
8
|
+
|
9
|
+
fqdn = opt.payload[0]
|
10
|
+
command = opt.payload[1]
|
11
|
+
args = opt.payload[2..-1]
|
12
|
+
|
13
|
+
unless fqdn && command
|
14
|
+
puts Hieracles::Help.usage
|
15
|
+
exit(1)
|
16
|
+
end
|
17
|
+
|
18
|
+
if Hieracles::Format.method_defined? command
|
19
|
+
node = Hieracles::Node.new fqdn, opt.options
|
20
|
+
begin
|
21
|
+
formatter = Object.const_get("Hieracles::Formats::#{Hieracles::Config.format}")
|
22
|
+
rescue
|
23
|
+
puts " Unknown format #{Hieracles::Config.format}"
|
24
|
+
exit(1)
|
25
|
+
end
|
26
|
+
dispatch = formatter.new node
|
27
|
+
puts dispatch.send(command.to_sym, args)
|
28
|
+
else
|
29
|
+
puts " Unknown command: #{command}"
|
30
|
+
Hieracles::Help.usage
|
31
|
+
exit(1)
|
32
|
+
end
|
data/bin/nodeinfo
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This is a cgi script intended to be installed on
|
3
|
+
# puppetmasters v2.6 and v2.7
|
4
|
+
|
5
|
+
require 'mysql'
|
6
|
+
require 'cgi'
|
7
|
+
|
8
|
+
cgi = CGI.new
|
9
|
+
|
10
|
+
if cgi['q'].empty?
|
11
|
+
puts "Content-type: text/plain\n\n"
|
12
|
+
puts "KO"
|
13
|
+
exit(0)
|
14
|
+
end
|
15
|
+
|
16
|
+
DB_HOST = 'localhost'
|
17
|
+
DB_USER = ''
|
18
|
+
DB_PASS = ''
|
19
|
+
DB_FIELDS = %w(farm site country)
|
20
|
+
|
21
|
+
fqdn = cgi['q'].gsub(/[^-_0-9a-zA-z\.]/, '')
|
22
|
+
QUERY = "select #{DB_FIELDS.join(', ')} from node left join datacenter dc on node.site=dc.datacenter where nodename='#{fqdn}';"
|
23
|
+
DB = "puppet"
|
24
|
+
|
25
|
+
|
26
|
+
begin
|
27
|
+
puts "Content-type: text/plain\n\n"
|
28
|
+
con = Mysql.new DB_HOST, DB_USER, DB_PASS
|
29
|
+
rs = con.query "use " + DB
|
30
|
+
rs = con.query QUERY
|
31
|
+
rs.each do |r|
|
32
|
+
puts r.join(',')
|
33
|
+
end
|
34
|
+
|
35
|
+
rescue Mysql::Error => e
|
36
|
+
puts e.errno
|
37
|
+
puts e.error
|
38
|
+
|
39
|
+
ensure
|
40
|
+
con.close if con
|
41
|
+
end
|
data/hieracles.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "hieracles"
|
7
|
+
spec.version = File.read(File.expand_path('../CHANGELOG.md', __FILE__))[/([0-9]+\.[0-9]+\.[0-9]+)/]
|
8
|
+
spec.authors = ["mose"]
|
9
|
+
spec.email = ["mose@gandi.net"]
|
10
|
+
spec.summary = %q{CLI tool for Hiera parameters visualisation.}
|
11
|
+
spec.description = %q{CLI tool for Hiera parameters visualisation and analysis.}
|
12
|
+
spec.homepage = "https://github.com/Gandi/hieracles"
|
13
|
+
spec.metadata = { "changelog" => "https://github.com/Gandi/hieracles/blob/master/CHANGELOG.md" }
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
#spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.executables = ['hc']
|
19
|
+
spec.test_files = spec.files.grep(%r{^spec/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency 'rspec', "~> 3.0"
|
25
|
+
spec.add_development_dependency 'fivemat'
|
26
|
+
spec.add_development_dependency 'coveralls'
|
27
|
+
spec.add_development_dependency 'simplecov'
|
28
|
+
spec.add_development_dependency 'rubocop'
|
29
|
+
|
30
|
+
end
|
data/lib/hieracles.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'hieracles/optparse'
|
2
|
+
require 'hieracles/config'
|
3
|
+
require 'hieracles/hiera'
|
4
|
+
require 'hieracles/utils'
|
5
|
+
require 'hieracles/help'
|
6
|
+
require 'hieracles/node'
|
7
|
+
require 'hieracles/format'
|
8
|
+
require 'hieracles/formats/csv'
|
9
|
+
require 'hieracles/formats/yaml'
|
10
|
+
require 'hieracles/formats/plain'
|
11
|
+
require 'hieracles/formats/console'
|
12
|
+
|
13
|
+
# https://github.com/Gandi/hieracles
|
14
|
+
module Hieracles
|
15
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Hieracles
|
4
|
+
# configuration singleton
|
5
|
+
module Config
|
6
|
+
extend self
|
7
|
+
|
8
|
+
attr_reader :extraparams, :server, :classpath,
|
9
|
+
:modulepath, :hierafile, :basepath, :encpath, :format
|
10
|
+
|
11
|
+
def load(options)
|
12
|
+
@optionfile = options[:config] || defaultconfig
|
13
|
+
@extraparams = extract_params(options[:params])
|
14
|
+
initconfig(@optionfile) unless File.exist? @optionfile
|
15
|
+
values = YAML.load_file(@optionfile)
|
16
|
+
@server = values['server']
|
17
|
+
@classpath = values['classpath']
|
18
|
+
@modulepath = values['modulepath'] || 'modules'
|
19
|
+
@encpath = options[:encpath] || values['encpath'] || 'enc'
|
20
|
+
@basepath = File.expand_path(options[:basepath] || values['basepath'] || '.')
|
21
|
+
@hierafile = options[:hierafile] || values['hierafile'] || 'hiera.yaml'
|
22
|
+
@format = (options[:format] || values['format'] || 'console').capitalize
|
23
|
+
end
|
24
|
+
|
25
|
+
def initconfig(file)
|
26
|
+
FileUtils.mkdir_p(File.dirname(file))
|
27
|
+
File.open(file, 'w') do |f|
|
28
|
+
f.puts '---'
|
29
|
+
f.puts '# uncomment if you use the CGI method for discovery'
|
30
|
+
f.puts '# server: puppetserver.example.com'
|
31
|
+
f.puts 'classpath: manifests/classes/%s.pp'
|
32
|
+
f.puts 'modulepath: modules'
|
33
|
+
f.puts 'encpath: enc'
|
34
|
+
f.puts 'hierafile: hiera.yaml'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def defaultconfig
|
39
|
+
File.join(ENV['HOME'], '.config', 'hieracles', 'config.yml')
|
40
|
+
end
|
41
|
+
|
42
|
+
# str is like: something=xxx;another=yyy
|
43
|
+
def extract_params(str)
|
44
|
+
return {} unless str
|
45
|
+
str.split(';').reduce({}) do |a, k|
|
46
|
+
a["#{k[/^[^=]*/]}".to_sym] = k[/[^=]*$/]
|
47
|
+
a
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def path(what)
|
52
|
+
File.join(@basepath, send(what.to_sym))
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Hieracles
|
2
|
+
class Format
|
3
|
+
def initialize(node)
|
4
|
+
@node = node
|
5
|
+
end
|
6
|
+
|
7
|
+
def info(_)
|
8
|
+
"#{__callee__} not implemented, please inherit from the Hieracles::Format class to implement a format.\n"
|
9
|
+
end
|
10
|
+
|
11
|
+
def files(_)
|
12
|
+
"#{__callee__} not implemented, please inherit from the Hieracles::Format class to implement a format.\n"
|
13
|
+
end
|
14
|
+
|
15
|
+
def paths(_)
|
16
|
+
"#{__callee__} not implemented, please inherit from the Hieracles::Format class to implement a format.\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
def params(args)
|
20
|
+
show_params(true, args)
|
21
|
+
end
|
22
|
+
|
23
|
+
def allparams(args)
|
24
|
+
show_params(false, args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def show_params(without_common, args)
|
28
|
+
filter = args[0]
|
29
|
+
output = build_head(without_common)
|
30
|
+
@node.params(without_common).each do |k, v|
|
31
|
+
output << build_params_line(k, v, filter)
|
32
|
+
end
|
33
|
+
output
|
34
|
+
end
|
35
|
+
|
36
|
+
def modules(args)
|
37
|
+
output = ''
|
38
|
+
@node.modules.each do |k, v|
|
39
|
+
output << build_modules_line(k, v)
|
40
|
+
end
|
41
|
+
output
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def build_head(without_common)
|
47
|
+
"#{__callee__} not implemented, please inherit from the Hieracles::Format class to implement a format.\n"
|
48
|
+
end
|
49
|
+
|
50
|
+
def build_params_line(key, value, filter)
|
51
|
+
"#{__callee__} not implemented, please inherit from the Hieracles::Format class to implement a format.\n"
|
52
|
+
end
|
53
|
+
|
54
|
+
def build_modules_line(key, value)
|
55
|
+
"#{__callee__} not implemented, please inherit from the Hieracles::Format class to implement a format.\n"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Hieracles
|
2
|
+
module Formats
|
3
|
+
# format accepting colors
|
4
|
+
# for display in the terminal
|
5
|
+
class Console < Hieracles::Format
|
6
|
+
include Hieracles::Utils
|
7
|
+
|
8
|
+
COLORS = [
|
9
|
+
"\e[31m%s\e[0m",
|
10
|
+
"\e[32m%s\e[0m",
|
11
|
+
"\e[33m%s\e[0m",
|
12
|
+
"\e[34m%s\e[0m",
|
13
|
+
"\e[35m%s\e[0m",
|
14
|
+
"\e[36m%s\e[0m",
|
15
|
+
"\e[37m%s\e[0m",
|
16
|
+
"\e[38m%s\e[0m",
|
17
|
+
"\e[97m%s\e[0m"
|
18
|
+
]
|
19
|
+
|
20
|
+
def initialize(node)
|
21
|
+
@colors = {}
|
22
|
+
super(node)
|
23
|
+
end
|
24
|
+
|
25
|
+
def info(_)
|
26
|
+
back = ''
|
27
|
+
length = max_key_length(@node.info) + 2
|
28
|
+
title = format(COLORS[8], "%-#{length}s")
|
29
|
+
@node.info.each do |k, v|
|
30
|
+
back << format("#{title} %s\n", k, v)
|
31
|
+
end
|
32
|
+
back
|
33
|
+
end
|
34
|
+
|
35
|
+
def files(_)
|
36
|
+
@node.files.join("\n") + "\n"
|
37
|
+
end
|
38
|
+
|
39
|
+
def paths(_)
|
40
|
+
@node.paths.join("\n") + "\n"
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_head(without_common)
|
44
|
+
output = ''
|
45
|
+
@node.files(without_common).each_with_index do |f, i|
|
46
|
+
output << format("#{COLORS[i]}\n", "[#{i}] #{f}")
|
47
|
+
@colors[f] = i
|
48
|
+
end
|
49
|
+
"#{output}\n"
|
50
|
+
end
|
51
|
+
|
52
|
+
def build_params_line(key, value, filter)
|
53
|
+
output = ''
|
54
|
+
if !filter || Regexp.new(filter).match(key)
|
55
|
+
first = value.shift
|
56
|
+
filecolor_index = @colors[first[:file]]
|
57
|
+
filecolor = COLORS[filecolor_index]
|
58
|
+
output << format("#{filecolor} #{COLORS[5]} %s\n",
|
59
|
+
"[#{filecolor_index}]",
|
60
|
+
key,
|
61
|
+
first[:value].to_s.gsub('%', '%%')
|
62
|
+
)
|
63
|
+
while value.count > 0
|
64
|
+
overriden = value.shift
|
65
|
+
filecolor_index = @colors[overriden[:file]]
|
66
|
+
output << format(" #{COLORS[8]}\n",
|
67
|
+
"[#{filecolor_index}] #{key} #{overriden[:value]}"
|
68
|
+
)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
output
|
72
|
+
end
|
73
|
+
|
74
|
+
def build_modules_line(key, value)
|
75
|
+
length = max_key_length(@node.modules) + 3
|
76
|
+
value_color = '%s'
|
77
|
+
value_color = COLORS[0] if /not found/i.match value
|
78
|
+
value_color = COLORS[2] if /\(duplicate\)/i.match value
|
79
|
+
format("%-#{length}s #{value_color}\n", key, value)
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|