hieraviz 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.
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