hieraviz 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +9 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +40 -0
  5. data/app/apiv1.rb +58 -0
  6. data/app/common.rb +22 -0
  7. data/app/config/hieraviz.default.yml +13 -0
  8. data/app/config/hieraviz.yml +13 -0
  9. data/app/main.rb +5 -0
  10. data/app/public/css/main.css +241 -0
  11. data/app/public/img/loader.gif +0 -0
  12. data/app/public/js/farms.js +60 -0
  13. data/app/public/js/logout.js +13 -0
  14. data/app/public/js/main.js +98 -0
  15. data/app/public/js/modules.js +40 -0
  16. data/app/public/js/nodes.js +145 -0
  17. data/app/public/js/resources.js +40 -0
  18. data/app/views/_foot.erb +3 -0
  19. data/app/views/_head.erb +14 -0
  20. data/app/views/_layout.erb +24 -0
  21. data/app/views/farms.erb +16 -0
  22. data/app/views/home.erb +3 -0
  23. data/app/views/logout.erb +7 -0
  24. data/app/views/modules.erb +8 -0
  25. data/app/views/nodes.erb +16 -0
  26. data/app/views/not_found.erb +3 -0
  27. data/app/views/resources.erb +8 -0
  28. data/app/web.rb +81 -0
  29. data/bin/hv-ctl +3 -0
  30. data/config.ru +8 -0
  31. data/lib/hieraviz/store.rb +17 -0
  32. data/lib/hieraviz/version.rb +3 -0
  33. data/lib/hieraviz.rb +6 -0
  34. data/spec/app/apiv1_spec.rb +12 -0
  35. data/spec/app/web_spec.rb +12 -0
  36. data/spec/files/config.yml +12 -0
  37. data/spec/files/hiera.yml +10 -0
  38. data/spec/files/puppet/enc/node1.example.com.yaml +7 -0
  39. data/spec/files/puppet/farm_modules/farm1/manifests/init.pp +3 -0
  40. data/spec/files/puppet/hiera.yml +10 -0
  41. data/spec/files/puppet/modules/module1/init.pp +2 -0
  42. data/spec/files/puppet/params/common/common.yml +2 -0
  43. data/spec/files/puppet/params/nodes/node1.example.com.yaml +2 -0
  44. data/spec/spec_helper.rb +23 -0
  45. 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
+ });
@@ -0,0 +1,3 @@
1
+ footer
2
+ <span class="debug">
3
+ </span>
@@ -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>
@@ -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>
@@ -0,0 +1,3 @@
1
+ <div class="meat text">
2
+ Welcome to hieraviz
3
+ </div>
@@ -0,0 +1,7 @@
1
+ <% content_for :more_js do %>
2
+ <script src="js/logout.js"></script>
3
+ <% end %>
4
+
5
+ <div class="meat text">
6
+ Please login again.
7
+ </div>
@@ -0,0 +1,8 @@
1
+ <% content_for :more_js do %>
2
+ <script async="async" src="js/modules.js"></script>
3
+ <% end %>
4
+
5
+ <pre class="meat">
6
+ WIP
7
+ </pre>
8
+
@@ -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>
@@ -0,0 +1,3 @@
1
+ <div class="meat">
2
+ Page not found
3
+ </div>
@@ -0,0 +1,8 @@
1
+ <% content_for :more_js do %>
2
+ <script src="js/resources.js"></script>
3
+ <% end %>
4
+
5
+ <pre class="meat">
6
+ WIP
7
+ </pre>
8
+
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
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ echo "nothing here yet"
data/config.ru ADDED
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require File.expand_path '../app/main.rb', __FILE__
4
+
5
+ run Rack::URLMap.new({
6
+ '/' => HieravizApp::Web,
7
+ '/v1' => HieravizApp::ApiV1
8
+ })
@@ -0,0 +1,17 @@
1
+ module Hieraviz
2
+ class Store
3
+
4
+ def initialize
5
+ @data = {}
6
+ end
7
+
8
+ def set(key, value)
9
+ @data[key.to_sym] = value
10
+ end
11
+
12
+ def get(key)
13
+ @data[key.to_sym]
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module Hieraviz
2
+ VERSION = "0.1.0"
3
+ end
data/lib/hieraviz.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "hieraviz/version"
2
+ require "hieraviz/store"
3
+
4
+ module Hieraviz
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe HieravizApp::ApiV1 do
4
+
5
+ context "when GET /v1/nodes" do
6
+ it "replies 200" do
7
+ get '/nodes'
8
+ expect(last_response).to be_ok
9
+ end
10
+ end
11
+
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe HieravizApp::Web do
4
+
5
+ context "when GET /" do
6
+ it "replies 401" do
7
+ get '/'
8
+ expect(last_response.status).to be 401
9
+ end
10
+ end
11
+
12
+ end
@@ -0,0 +1,12 @@
1
+ ---
2
+ basepath: "spec/files/puppet"
3
+ classpath: "farm_modules/%s/manifests/init.pp"
4
+ hierafile: "hiera.yml"
5
+ usedb: false
6
+ puppetdb:
7
+ usessl: false
8
+ host: puppetdb.example.com
9
+ port: 8080
10
+ http_auth:
11
+ username: 'toto'
12
+ password: 'toto'
@@ -0,0 +1,10 @@
1
+ ---
2
+ :backends:
3
+ - yaml
4
+ :hierarchy:
5
+ - "nodes/%{fqdn}"
6
+ - "farm/%{farm}"
7
+ - "common/common"
8
+ :yaml:
9
+ :datadir: "params/"
10
+ :merge_behavior: deeper
@@ -0,0 +1,7 @@
1
+ ---
2
+ classes:
3
+ - farm1
4
+ parameters:
5
+ country: fr
6
+ datacenter: equinix
7
+ farm: dev
@@ -0,0 +1,3 @@
1
+ class farm1 {
2
+ include module1
3
+ }
@@ -0,0 +1,10 @@
1
+ ---
2
+ :backends:
3
+ - yaml
4
+ :hierarchy:
5
+ - "nodes/%{fqdn}"
6
+ - "farm/%{farm}"
7
+ - "common/common"
8
+ :yaml:
9
+ :datadir: "params/"
10
+ :merge_behavior: deeper
@@ -0,0 +1,2 @@
1
+ class module1 {
2
+ }
@@ -0,0 +1,2 @@
1
+ param1:
2
+ subparam1: value common
@@ -0,0 +1,2 @@
1
+ param1:
2
+ subparam1: value1
@@ -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