hieraviz 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +9 -0
- data/LICENSE.txt +21 -0
- data/README.md +40 -0
- data/app/apiv1.rb +58 -0
- data/app/common.rb +22 -0
- data/app/config/hieraviz.default.yml +13 -0
- data/app/config/hieraviz.yml +13 -0
- data/app/main.rb +5 -0
- data/app/public/css/main.css +241 -0
- data/app/public/img/loader.gif +0 -0
- data/app/public/js/farms.js +60 -0
- data/app/public/js/logout.js +13 -0
- data/app/public/js/main.js +98 -0
- data/app/public/js/modules.js +40 -0
- data/app/public/js/nodes.js +145 -0
- data/app/public/js/resources.js +40 -0
- data/app/views/_foot.erb +3 -0
- data/app/views/_head.erb +14 -0
- data/app/views/_layout.erb +24 -0
- data/app/views/farms.erb +16 -0
- data/app/views/home.erb +3 -0
- data/app/views/logout.erb +7 -0
- data/app/views/modules.erb +8 -0
- data/app/views/nodes.erb +16 -0
- data/app/views/not_found.erb +3 -0
- data/app/views/resources.erb +8 -0
- data/app/web.rb +81 -0
- data/bin/hv-ctl +3 -0
- data/config.ru +8 -0
- data/lib/hieraviz/store.rb +17 -0
- data/lib/hieraviz/version.rb +3 -0
- data/lib/hieraviz.rb +6 -0
- data/spec/app/apiv1_spec.rb +12 -0
- data/spec/app/web_spec.rb +12 -0
- data/spec/files/config.yml +12 -0
- data/spec/files/hiera.yml +10 -0
- data/spec/files/puppet/enc/node1.example.com.yaml +7 -0
- data/spec/files/puppet/farm_modules/farm1/manifests/init.pp +3 -0
- data/spec/files/puppet/hiera.yml +10 -0
- data/spec/files/puppet/modules/module1/init.pp +2 -0
- data/spec/files/puppet/params/common/common.yml +2 -0
- data/spec/files/puppet/params/nodes/node1.example.com.yaml +2 -0
- data/spec/spec_helper.rb +23 -0
- metadata +257 -0
@@ -0,0 +1,145 @@
|
|
1
|
+
/*
|
2
|
+
We don't need jQuery fat mama
|
3
|
+
http://youmightnotneedjquery.com/
|
4
|
+
https://github.com/oneuijs/You-Dont-Need-jQuery
|
5
|
+
|
6
|
+
also
|
7
|
+
We don't need to care about freaking IE
|
8
|
+
let's use the fetch API for ajax calls
|
9
|
+
https://fetch.spec.whatwg.org
|
10
|
+
*/
|
11
|
+
|
12
|
+
ready( () => {
|
13
|
+
|
14
|
+
var meat = document.querySelector('div.meat');
|
15
|
+
var nodes = document.querySelectorAll('li.node');
|
16
|
+
focusNav('nodes');
|
17
|
+
filterBox(".filter input", nodes);
|
18
|
+
|
19
|
+
function build_line(top, file, key, value, overriden) {
|
20
|
+
if (overriden === true) {
|
21
|
+
rowclass = "row overriden";
|
22
|
+
} else {
|
23
|
+
rowclass = "row";
|
24
|
+
}
|
25
|
+
addTo(top, "<div class=\""+rowclass+"\">" +
|
26
|
+
"<div class=\"paramfile\">"+shortParamFile(file)+"</div>\n" +
|
27
|
+
"<div class=\"data\">"+key.replace(/\./g,' . ')+"</div>\n" +
|
28
|
+
"<pre class=\"value\">"+JSON.stringify(value, null, 2)+"</pre>\n" +
|
29
|
+
"</div>");
|
30
|
+
}
|
31
|
+
|
32
|
+
function build_row(top, key, params) {
|
33
|
+
build_line(top, params['file'], key, params['value'], false);
|
34
|
+
if (params['overriden'] == true) {
|
35
|
+
Array.prototype.forEach.call(params['found_in'], (values, i) => {
|
36
|
+
build_line(top, values['file'], key, values['value'], true);
|
37
|
+
});
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
function focus_on(els, el) {
|
42
|
+
Array.prototype.forEach.call(els, (item, i) => {
|
43
|
+
removeClass(item, 'focus');
|
44
|
+
});
|
45
|
+
addClass(el, 'focus');
|
46
|
+
}
|
47
|
+
|
48
|
+
function build_top(title) {
|
49
|
+
meat.innerHTML = "<h3>Node "+title+"</h3>";
|
50
|
+
addTo(meat, "<div class=\"nodenav\">" +
|
51
|
+
"<span class=\"showinfo\" data-node=\""+title+"\">Info</span>" +
|
52
|
+
"<span class=\"showparams\" data-node=\""+title+"\">Params</span>" +
|
53
|
+
"<span class=\"showallparams\" data-node=\""+title+"\">AllParams</span>" +
|
54
|
+
"</div>");
|
55
|
+
addTo(meat, "<div class=\"paramfilter\">" +
|
56
|
+
"<input type=\"text\" name=\"paramfilter\" />" +
|
57
|
+
"</div>");
|
58
|
+
}
|
59
|
+
|
60
|
+
function build_info(top, title, hash) {
|
61
|
+
|
62
|
+
}
|
63
|
+
|
64
|
+
function build_params(top, title, hash) {
|
65
|
+
if (Object.keys(hash).length > 0) {
|
66
|
+
Array.prototype.forEach.call(Object.keys(hash), (item, k) => {
|
67
|
+
build_row(top, item, hash[item]);
|
68
|
+
});
|
69
|
+
var rows = document.querySelectorAll('div.row');
|
70
|
+
filterBox(".paramfilter input", rows);
|
71
|
+
} else {
|
72
|
+
addTo(top, "<div>There is no params in this node.</div>\n");
|
73
|
+
}
|
74
|
+
window.location.hash = '#'+title;
|
75
|
+
}
|
76
|
+
|
77
|
+
|
78
|
+
function rebuild_nav(title) {
|
79
|
+
var nodelinks = document.querySelectorAll('div.nodenav span');
|
80
|
+
Array.prototype.forEach.call(nodelinks, (item, i) => {
|
81
|
+
item.addEventListener('click', (ev) => {
|
82
|
+
start_wait();
|
83
|
+
el = ev.target;
|
84
|
+
action = el.innerText.toLowerCase();
|
85
|
+
fetch('/v1/node/' + title + '/' + action).
|
86
|
+
then(res => res.json()).
|
87
|
+
then(j => {
|
88
|
+
focus_on(nodelinks, el);
|
89
|
+
end_wait();
|
90
|
+
});
|
91
|
+
});
|
92
|
+
});
|
93
|
+
}
|
94
|
+
|
95
|
+
var Node = {
|
96
|
+
params: function(el) {
|
97
|
+
start_wait(meat);
|
98
|
+
title = el.dataset.node;
|
99
|
+
fetch('/v1/node/' + title).
|
100
|
+
then(res => res.json()).
|
101
|
+
then(j => {
|
102
|
+
build_top(title);
|
103
|
+
build_params(meat, title, j);
|
104
|
+
rebuild_nav(title);
|
105
|
+
end_wait(meat);
|
106
|
+
});
|
107
|
+
},
|
108
|
+
|
109
|
+
info: function(el) {
|
110
|
+
start_wait(meat);
|
111
|
+
title = el.dataset.node;
|
112
|
+
fetch('/v1/node/' + title + '/info').
|
113
|
+
then(res => res.json()).
|
114
|
+
then(j => {
|
115
|
+
build_top(title);
|
116
|
+
build_info(meat, title, j);
|
117
|
+
rebuild_nav(title);
|
118
|
+
end_wait(meat);
|
119
|
+
});
|
120
|
+
},
|
121
|
+
|
122
|
+
allparams: function(el) {
|
123
|
+
start_wait(meat);
|
124
|
+
title = el.dataset.node;
|
125
|
+
fetch('/v1/node/' + title + '/all').
|
126
|
+
then(res => res.json()).
|
127
|
+
then(j => {
|
128
|
+
build_top(title);
|
129
|
+
build_info(meat, title, j);
|
130
|
+
rebuild_nav(title);
|
131
|
+
end_wait(meat);
|
132
|
+
});
|
133
|
+
},
|
134
|
+
}
|
135
|
+
|
136
|
+
/* declaration of events for the nodes menu */
|
137
|
+
Array.prototype.forEach.call(nodes, (item, i) => {
|
138
|
+
item.addEventListener('click', (ev) => {
|
139
|
+
Node.params(ev.target);
|
140
|
+
});
|
141
|
+
});
|
142
|
+
|
143
|
+
restore_url(nodes);
|
144
|
+
|
145
|
+
});
|
@@ -0,0 +1,40 @@
|
|
1
|
+
/*
|
2
|
+
We don't need jQuery fat mama
|
3
|
+
http://youmightnotneedjquery.com/
|
4
|
+
https://github.com/oneuijs/You-Dont-Need-jQuery
|
5
|
+
|
6
|
+
also
|
7
|
+
We don't need to care about freaking IE
|
8
|
+
let's use the fetch API for ajax calls
|
9
|
+
https://fetch.spec.whatwg.org
|
10
|
+
*/
|
11
|
+
|
12
|
+
function ready(fn) {
|
13
|
+
if (document.readyState != 'loading') {
|
14
|
+
fn();
|
15
|
+
} else {
|
16
|
+
document.addEventListener('DOMContentLoaded', fn);
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
ready( () => {
|
21
|
+
focusNav('resources');
|
22
|
+
|
23
|
+
// var nodes = document.querySelectorAll('li.node');
|
24
|
+
// var meat = document.querySelector('pre.meat');
|
25
|
+
|
26
|
+
// Array.prototype.forEach.call(nodes, (item, i) => {
|
27
|
+
// item.addEventListener('click', (ev) => {
|
28
|
+
// el = ev.target;
|
29
|
+
// fetch('/v1/node/' + el.innerText).
|
30
|
+
// then(res => res.json()).
|
31
|
+
// then(j => {
|
32
|
+
// meat.textContent = JSON.stringify(j);
|
33
|
+
// Array.prototype.forEach.call(nodes, (item, i) => {
|
34
|
+
// removeClass(item, 'focus')
|
35
|
+
// });
|
36
|
+
// addClass(el, 'focus')
|
37
|
+
// });
|
38
|
+
// });
|
39
|
+
// });
|
40
|
+
});
|
data/app/views/_foot.erb
ADDED
data/app/views/_head.erb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
<div class="title">
|
2
|
+
<a href="/">
|
3
|
+
<%= settings.app_name %>
|
4
|
+
</a>
|
5
|
+
</div>
|
6
|
+
<div class="nav">
|
7
|
+
<a href="/nodes" class="nodes">Nodes</a>
|
8
|
+
<a href="/farms" class="farms">Farms</a>
|
9
|
+
<a href="/modules" class="modules">Modules</a>
|
10
|
+
<a href="/resources" class="resources">Resources</a>
|
11
|
+
</div>
|
12
|
+
<div class="auth">
|
13
|
+
<a href="/logout" id="logout">Logout</a>
|
14
|
+
</div>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<title>Hieraviz
|
5
|
+
<%= @title if @title %>
|
6
|
+
</title>
|
7
|
+
<link href="css/main.css" rel="stylesheet" type="text/css">
|
8
|
+
<script src="js/main.js"></script>
|
9
|
+
<%= yield_content :more_js %>
|
10
|
+
</head>
|
11
|
+
<body>
|
12
|
+
<div id="container">
|
13
|
+
<div class="head">
|
14
|
+
<%= erb :_head, :layout => false %>
|
15
|
+
</div>
|
16
|
+
<div class="content">
|
17
|
+
<%= yield %>
|
18
|
+
</div>
|
19
|
+
<div class="foot">
|
20
|
+
<%= erb :_foot, :layout => false %>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
</body>
|
24
|
+
</html>
|
data/app/views/farms.erb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
<% content_for :more_js do %>
|
2
|
+
<script src="js/farms.js"></script>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<div class="side">
|
6
|
+
<form class="filter">
|
7
|
+
<input type="text" name="filter" />
|
8
|
+
</form>
|
9
|
+
<ul>
|
10
|
+
<% @farms.each do |farm| %>
|
11
|
+
<li class="farm"><%= farm %></li>
|
12
|
+
<% end %>
|
13
|
+
</ul>
|
14
|
+
</div>
|
15
|
+
<div class="meat farms">
|
16
|
+
</div>
|
data/app/views/home.erb
ADDED
data/app/views/nodes.erb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
<% content_for :more_js do %>
|
2
|
+
<script src="js/nodes.js"></script>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<div class="side">
|
6
|
+
<form class="filter">
|
7
|
+
<input type="text" name="filter" />
|
8
|
+
</form>
|
9
|
+
<ul>
|
10
|
+
<% @nodes.each do |node| %>
|
11
|
+
<li class="node" data-node="<%= node %>"><%= node %></li>
|
12
|
+
<% end %>
|
13
|
+
</ul>
|
14
|
+
</div>
|
15
|
+
<div class="meat nodes">
|
16
|
+
</div>
|
data/app/web.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'sinatra/content_for'
|
2
|
+
|
3
|
+
require 'better_errors'
|
4
|
+
require 'digest/sha1'
|
5
|
+
require 'dotenv'
|
6
|
+
|
7
|
+
require 'hieracles'
|
8
|
+
require 'hieraviz'
|
9
|
+
|
10
|
+
require File.expand_path '../common.rb', __FILE__
|
11
|
+
|
12
|
+
module HieravizApp
|
13
|
+
class Web < Common
|
14
|
+
helpers Sinatra::ContentFor
|
15
|
+
|
16
|
+
configure do
|
17
|
+
set :public_folder, Proc.new { File.join(root, "public") }
|
18
|
+
set :views_folder, Proc.new { File.join(root, "views") }
|
19
|
+
set :erb, layout: :_layout
|
20
|
+
end
|
21
|
+
|
22
|
+
configure :development do
|
23
|
+
use BetterErrors::Middleware
|
24
|
+
BetterErrors.application_root = File.expand_path('..', __FILE__)
|
25
|
+
end
|
26
|
+
|
27
|
+
helpers do
|
28
|
+
def check_cookie
|
29
|
+
if !session[:hieraviz_key]
|
30
|
+
newkey = Digest::SHA1.hexdigest(Time.new.to_s)
|
31
|
+
store.set(:hieraviz_key, newkey)
|
32
|
+
session[:hieraviz_key] = newkey
|
33
|
+
end
|
34
|
+
end
|
35
|
+
def verify_key(key)
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
use Rack::Auth::Basic, "Puppet Private Access" do |username, password|
|
41
|
+
username == settings.configdata['http_auth']['username'] &&
|
42
|
+
password == settings.configdata['http_auth']['password']
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
get '/' do
|
47
|
+
erb :home
|
48
|
+
end
|
49
|
+
|
50
|
+
get '/nodes' do
|
51
|
+
@nodes = Hieracles::Registry.nodes(settings.config)
|
52
|
+
erb :nodes
|
53
|
+
end
|
54
|
+
|
55
|
+
get '/farms' do
|
56
|
+
@farms = Hieracles::Registry.farms(settings.config)
|
57
|
+
erb :farms
|
58
|
+
end
|
59
|
+
|
60
|
+
get '/modules' do
|
61
|
+
erb :farms
|
62
|
+
end
|
63
|
+
|
64
|
+
get '/resources' do
|
65
|
+
erb :farms
|
66
|
+
end
|
67
|
+
|
68
|
+
get '/logout' do
|
69
|
+
erb :logout, layout: :_layout
|
70
|
+
end
|
71
|
+
|
72
|
+
not_found do
|
73
|
+
erb :not_found, layout: :_layout
|
74
|
+
end
|
75
|
+
|
76
|
+
error 401 do
|
77
|
+
'Access forbidden'
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
data/bin/hv-ctl
ADDED
data/config.ru
ADDED
data/lib/hieraviz.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
require 'hieraviz'
|
3
|
+
|
4
|
+
require 'rack/test'
|
5
|
+
require 'rspec'
|
6
|
+
|
7
|
+
ENV['RACK_ENV'] = 'test'
|
8
|
+
ENV['HIERAVIZ_CONFIG_FILE'] = File.expand_path '../files/config.yml', __FILE__
|
9
|
+
|
10
|
+
require File.expand_path '../../app/main.rb', __FILE__
|
11
|
+
|
12
|
+
module RSpecMixin
|
13
|
+
include Rack::Test::Methods
|
14
|
+
def app() described_class end
|
15
|
+
end
|
16
|
+
|
17
|
+
RSpec.configure do |config|
|
18
|
+
config.include RSpecMixin
|
19
|
+
config.mock_with :rspec
|
20
|
+
config.expect_with :rspec do |c|
|
21
|
+
c.syntax = :expect
|
22
|
+
end
|
23
|
+
end
|