puppet-herald 0.1.1 → 0.2.0
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 +15 -7
- data/.rubocop.yml +31 -0
- data/.rubocop_todo.yml +6 -0
- data/.travis.yml +7 -7
- data/Gemfile +5 -9
- data/README.md +152 -16
- data/Rakefile +67 -6
- data/bin/puppet-herald +1 -1
- data/config.ru +2 -2
- data/db/migrate/20141211165540_create_nodes.rb +5 -3
- data/db/migrate/20141211171305_create_reports.rb +12 -10
- data/db/migrate/20141211171326_create_log_entries.rb +9 -7
- data/db/schema.rb +24 -26
- data/lib/puppet-herald.rb +59 -21
- data/lib/puppet-herald/app/api.rb +111 -0
- data/lib/puppet-herald/app/configuration.rb +70 -0
- data/lib/puppet-herald/app/frontend.rb +61 -0
- data/lib/puppet-herald/{views → app/views}/app.erb +5 -8
- data/lib/puppet-herald/{views → app/views}/err500.erb +1 -4
- data/lib/puppet-herald/application.rb +27 -0
- data/lib/puppet-herald/cli.rb +66 -45
- data/lib/puppet-herald/client.rb +33 -0
- data/lib/puppet-herald/database.rb +84 -40
- data/lib/puppet-herald/javascript.rb +23 -17
- data/lib/puppet-herald/models/log-entry.rb +10 -3
- data/lib/puppet-herald/models/node.rb +15 -5
- data/lib/puppet-herald/models/report.rb +70 -63
- data/lib/puppet-herald/public/app.js +9 -8
- data/lib/puppet-herald/public/components/directives/status-button.html +1 -1
- data/lib/puppet-herald/public/components/directives/status-button.js +5 -3
- data/lib/puppet-herald/public/components/filters/filters.js +9 -4
- data/lib/puppet-herald/public/components/page.js +34 -0
- data/lib/puppet-herald/public/node/node.html +3 -1
- data/lib/puppet-herald/public/node/node.js +7 -4
- data/lib/puppet-herald/public/nodes/nodes.js +3 -2
- data/lib/puppet-herald/public/report/report.html +4 -1
- data/lib/puppet-herald/public/report/report.js +5 -3
- data/lib/puppet-herald/stubs/puppet.rb +20 -9
- data/lib/puppet-herald/version.rb +17 -7
- data/package.json +8 -3
- data/puppet-herald.gemspec +3 -6
- data/spec/integration/application_spec.rb +175 -0
- data/spec/integration/models/node_spec.rb +4 -4
- data/spec/integration/models/report_spec.rb +7 -7
- data/spec/spec_helper.rb +12 -7
- data/spec/support/active_record.rb +6 -10
- data/spec/support/reconnectdb.rb +13 -0
- data/spec/unit/puppet-herald/cli_spec.rb +45 -13
- data/spec/unit/puppet-herald/client_spec.rb +23 -0
- data/spec/unit/puppet-herald/database_spec.rb +8 -9
- data/spec/unit/puppet-herald/javascript_spec.rb +8 -13
- data/spec/unit/puppet-herald_spec.rb +4 -4
- data/test/javascript/karma.conf.js +43 -5
- data/test/javascript/src/app_test.js +90 -0
- data/test/javascript/src/components/artifact/artifact-directive_test.js +36 -0
- data/test/javascript/src/components/artifact/artifact_test.js +64 -0
- data/test/javascript/src/components/directives/status-button_test.js +159 -0
- data/test/javascript/src/components/filters/filters_test.js +35 -0
- data/test/javascript/src/node/node_test.js +87 -0
- data/test/javascript/src/nodes/nodes_test.js +56 -0
- data/test/javascript/src/report/report_test.js +94 -0
- metadata +98 -68
- data/lib/puppet-herald/app.rb +0 -103
- data/lib/puppet-herald/public/components/artifact/artifact-directive_test.js +0 -17
- data/spec/integration/app_spec.rb +0 -21
@@ -1,13 +1,15 @@
|
|
1
|
+
# Migration
|
1
2
|
class CreateLogEntries < ActiveRecord::Migration
|
3
|
+
# Migration
|
2
4
|
def change
|
3
5
|
create_table :log_entries do |t|
|
4
|
-
t.datetime
|
5
|
-
t.string
|
6
|
-
t.string
|
7
|
-
t.integer
|
8
|
-
t.text
|
9
|
-
|
10
|
-
t.references
|
6
|
+
t.datetime :time
|
7
|
+
t.string :level
|
8
|
+
t.string :source
|
9
|
+
t.integer :line
|
10
|
+
t.text :message
|
11
|
+
|
12
|
+
t.references :report
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
data/db/schema.rb
CHANGED
@@ -11,37 +11,35 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended that you check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(version:
|
15
|
-
|
14
|
+
ActiveRecord::Schema.define(version: 20_141_211_171_326) do
|
16
15
|
# These are extensions that must be enabled in order to support this database
|
17
|
-
enable_extension
|
16
|
+
enable_extension 'plpgsql'
|
18
17
|
|
19
|
-
create_table
|
20
|
-
t.datetime
|
21
|
-
t.string
|
22
|
-
t.string
|
23
|
-
t.integer
|
24
|
-
t.text
|
25
|
-
t.integer
|
18
|
+
create_table 'log_entries', force: true do |t|
|
19
|
+
t.datetime 'time'
|
20
|
+
t.string 'level'
|
21
|
+
t.string 'source'
|
22
|
+
t.integer 'line'
|
23
|
+
t.text 'message'
|
24
|
+
t.integer 'report_id'
|
26
25
|
end
|
27
26
|
|
28
|
-
create_table
|
29
|
-
t.string
|
30
|
-
t.string
|
31
|
-
t.integer
|
32
|
-
t.datetime
|
27
|
+
create_table 'nodes', force: true do |t|
|
28
|
+
t.string 'name'
|
29
|
+
t.string 'status'
|
30
|
+
t.integer 'no_of_reports'
|
31
|
+
t.datetime 'last_run'
|
33
32
|
end
|
34
33
|
|
35
|
-
create_table
|
36
|
-
t.string
|
37
|
-
t.string
|
38
|
-
t.string
|
39
|
-
t.string
|
40
|
-
t.string
|
41
|
-
t.string
|
42
|
-
t.string
|
43
|
-
t.datetime
|
44
|
-
t.integer
|
34
|
+
create_table 'reports', force: true do |t|
|
35
|
+
t.string 'status'
|
36
|
+
t.string 'environment'
|
37
|
+
t.string 'transaction_uuid'
|
38
|
+
t.string 'configuration_version'
|
39
|
+
t.string 'puppet_version'
|
40
|
+
t.string 'kind'
|
41
|
+
t.string 'host'
|
42
|
+
t.datetime 'time'
|
43
|
+
t.integer 'node_id'
|
45
44
|
end
|
46
|
-
|
47
45
|
end
|
data/lib/puppet-herald.rb
CHANGED
@@ -1,49 +1,87 @@
|
|
1
1
|
begin
|
2
2
|
require 'pry'
|
3
|
-
rescue LoadError
|
3
|
+
rescue LoadError # rubocop:disable Lint/HandleExceptions
|
4
4
|
# Do nothing here
|
5
5
|
end
|
6
6
|
|
7
|
+
require 'puppet-herald/database'
|
8
|
+
|
9
|
+
# A module for Herald
|
7
10
|
module PuppetHerald
|
11
|
+
@root = File.dirname(File.dirname(File.realpath(__FILE__)))
|
12
|
+
@database = PuppetHerald::Database.new
|
8
13
|
|
9
|
-
|
14
|
+
# A database object
|
15
|
+
# @return [PuppetHerald::Database] a database object
|
16
|
+
def self.database # rubocop:disable Style/TrivialAccessors
|
17
|
+
@database
|
18
|
+
end
|
10
19
|
|
11
|
-
|
12
|
-
|
20
|
+
# Calculates a replative directory inside the project
|
21
|
+
#
|
22
|
+
# @param dir [String] a sub directory
|
23
|
+
# @return [String] a full path to replative dir
|
24
|
+
def self.relative_dir(dir)
|
25
|
+
File.realpath(File.join @root, dir)
|
13
26
|
end
|
14
27
|
|
28
|
+
def self.environment=(environment)
|
29
|
+
rackenv = :production
|
30
|
+
envsymbol = environment.to_s.to_sym
|
31
|
+
case envsymbol
|
32
|
+
when :dev, :development
|
33
|
+
rackenv = :development
|
34
|
+
when :test, :ci
|
35
|
+
rackenv = :test
|
36
|
+
else
|
37
|
+
rackenv = :production
|
38
|
+
envsymbol = :production
|
39
|
+
end
|
40
|
+
ENV['PUPPET_HERALD_ENV'] = envsymbol.to_s
|
41
|
+
ENV['RACK_ENV'] = rackenv.to_s
|
42
|
+
end
|
43
|
+
|
44
|
+
# Gets the environment set for Herald
|
45
|
+
# @return [Symbol] an environment
|
15
46
|
def self.environment
|
16
47
|
env = :production
|
17
|
-
unless ENV['PUPPET_HERALD_ENV'].nil?
|
18
|
-
|
19
|
-
|
20
|
-
return env
|
48
|
+
env = ENV['PUPPET_HERALD_ENV'].to_sym unless ENV['PUPPET_HERALD_ENV'].nil?
|
49
|
+
ENV['RACK_ENV'] = env.to_s
|
50
|
+
env
|
21
51
|
end
|
22
52
|
|
23
|
-
|
24
|
-
|
53
|
+
# Checks is running in DEVELOPMENT kind of environment (dev, ci, test)
|
54
|
+
#
|
55
|
+
# @return [Boolean] true if runs in development
|
56
|
+
def self.in_dev?
|
57
|
+
[:development, :dev, :test, :ci].include? environment
|
25
58
|
end
|
26
59
|
|
27
|
-
|
28
|
-
|
60
|
+
# Checks is running in production environment
|
61
|
+
#
|
62
|
+
# @return [Boolean] true if runs in production
|
63
|
+
def self.in_prod?
|
64
|
+
!in_dev?
|
29
65
|
end
|
30
66
|
|
31
|
-
|
67
|
+
# Reports a bug in desired format
|
68
|
+
#
|
69
|
+
# @param ex [Exception] an exception that was thrown
|
70
|
+
# @return [Hash] a hash with info about bug to be displayed to user
|
71
|
+
def self.bug(ex)
|
32
72
|
file = Tempfile.new(['puppet-herald-bug', '.log'])
|
33
73
|
filepath = file.path
|
34
74
|
file.close
|
35
75
|
file.unlink
|
36
|
-
message = "v#{PuppetHerald::VERSION}-#{ex.class
|
76
|
+
message = "v#{PuppetHerald::VERSION}-#{ex.class}: #{ex.message}"
|
37
77
|
contents = message + "\n\n" + ex.backtrace.join("\n") + "\n"
|
38
78
|
File.write(filepath, contents)
|
39
79
|
bugo = {
|
40
|
-
:
|
41
|
-
:
|
42
|
-
:
|
43
|
-
:
|
80
|
+
message: message,
|
81
|
+
homepage: PuppetHerald::HOMEPAGE,
|
82
|
+
bugfile: filepath,
|
83
|
+
help: "Please report this bug to #{PuppetHerald::HOMEPAGE} by passing contents of bug file: #{filepath}"
|
44
84
|
}
|
45
|
-
|
85
|
+
bugo
|
46
86
|
end
|
47
87
|
end
|
48
|
-
|
49
|
-
require 'puppet-herald/database'
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'sinatra/namespace'
|
3
|
+
require 'puppet-herald'
|
4
|
+
require 'puppet-herald/app/configuration'
|
5
|
+
require 'puppet-herald/models/node'
|
6
|
+
require 'puppet-herald/models/report'
|
7
|
+
|
8
|
+
# A module for Herald
|
9
|
+
module PuppetHerald
|
10
|
+
# Module that holds modules of Sinatra app
|
11
|
+
module App
|
12
|
+
# An implementation of API v1
|
13
|
+
class ApiImplV1
|
14
|
+
# Constructor
|
15
|
+
# @param app [Sinatra::Base] an app module
|
16
|
+
# @return [ApiImplV1] an API impl
|
17
|
+
def initialize(app)
|
18
|
+
@app = app
|
19
|
+
end
|
20
|
+
# Creates a new report
|
21
|
+
# @param request [Sinatra::Request] an request object
|
22
|
+
# @return [Array] an response array: [code, body] or [code, headers, body]
|
23
|
+
def post_reports(request)
|
24
|
+
yaml = request.body.read
|
25
|
+
report = PuppetHerald::Models::Report.create_from_yaml yaml
|
26
|
+
body = { id: report.id }.to_json
|
27
|
+
[201, body]
|
28
|
+
end
|
29
|
+
# Get a report by its ID
|
30
|
+
# @param params [Hash] an requests parsed params
|
31
|
+
# @return [Array] an response array: [code, body] or [code, headers, body]
|
32
|
+
def get_report(params)
|
33
|
+
id = params[:id]
|
34
|
+
report = PuppetHerald::Models::Report.get_with_log_entries(id)
|
35
|
+
status = 200
|
36
|
+
status = 404 if report.nil?
|
37
|
+
body = report.to_json(include: :log_entries)
|
38
|
+
[status, body]
|
39
|
+
end
|
40
|
+
# Gets all nodes
|
41
|
+
# @return [Array] an response array: [code, body] or [code, headers, body]
|
42
|
+
def nodes
|
43
|
+
nodes = PuppetHerald::Models::Node.all
|
44
|
+
[200, nodes.to_json]
|
45
|
+
end
|
46
|
+
# Gets a node by its ID
|
47
|
+
# @param params [Hash] an requests parsed params
|
48
|
+
# @return [Array] an response array: [code, body] or [code, headers, body]
|
49
|
+
def get_node(params)
|
50
|
+
id = params[:id]
|
51
|
+
node = PuppetHerald::Models::Node.get_with_reports(id)
|
52
|
+
status = 200
|
53
|
+
status = 404 if node.nil?
|
54
|
+
body = node.to_json(include: :reports)
|
55
|
+
[status, body]
|
56
|
+
end
|
57
|
+
# Get a app's artifact information
|
58
|
+
# @return [Array] an response array: [code, body] or [code, headers, body]
|
59
|
+
def version_json
|
60
|
+
ver = {}
|
61
|
+
[:VERSION, :LICENSE, :NAME, :PACKAGE, :SUMMARY, :DESCRIPTION, :HOMEPAGE].each do |const|
|
62
|
+
ver[const.downcase] = PuppetHerald.const_get const
|
63
|
+
end
|
64
|
+
[200, ver.to_json]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# An API app module
|
69
|
+
class Api < Sinatra::Base
|
70
|
+
register Sinatra::Namespace
|
71
|
+
use PuppetHerald::App::Configuration
|
72
|
+
set :api, ApiImplV1.new(self)
|
73
|
+
helpers do
|
74
|
+
# API getter
|
75
|
+
# @return [ApiImplV1] an api object
|
76
|
+
def api
|
77
|
+
settings.api
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
get '/version.json' do
|
82
|
+
content_type 'application/json'
|
83
|
+
api.version_json
|
84
|
+
end
|
85
|
+
|
86
|
+
namespace '/api' do
|
87
|
+
namespace '/v1' do
|
88
|
+
post '/reports' do
|
89
|
+
content_type 'application/json'
|
90
|
+
api.post_reports request
|
91
|
+
end
|
92
|
+
|
93
|
+
get '/nodes' do
|
94
|
+
content_type 'application/json'
|
95
|
+
api.nodes
|
96
|
+
end
|
97
|
+
|
98
|
+
get '/nodes/:id' do
|
99
|
+
content_type 'application/json'
|
100
|
+
api.get_node params
|
101
|
+
end
|
102
|
+
|
103
|
+
get '/reports/:id' do
|
104
|
+
content_type 'application/json'
|
105
|
+
api.get_report params
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'sinatra/base'
|
3
|
+
require 'sinatra/namespace'
|
4
|
+
require 'sinatra/activerecord'
|
5
|
+
require 'puppet-herald'
|
6
|
+
require 'puppet-herald/javascript'
|
7
|
+
|
8
|
+
# A module for Herald
|
9
|
+
module PuppetHerald
|
10
|
+
# A module that holds module of app
|
11
|
+
module App
|
12
|
+
# A configuration for application
|
13
|
+
class Configuration < Sinatra::Base
|
14
|
+
register Sinatra::ActiveRecordExtension
|
15
|
+
|
16
|
+
set :database, PuppetHerald.database.spec unless PuppetHerald.database.spec.nil?
|
17
|
+
|
18
|
+
class << self
|
19
|
+
# Migrates a database to state desired for the application
|
20
|
+
#
|
21
|
+
# @return [nil]
|
22
|
+
def dbmigrate!
|
23
|
+
ActiveRecord::Base.establish_connection(PuppetHerald.database.spec)
|
24
|
+
setup_database_logger
|
25
|
+
ActiveRecord::Migrator.up 'db/migrate'
|
26
|
+
ActiveRecord::Base.clear_active_connections!
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# Is request part of the API
|
31
|
+
# @param req [Sinatra::Request] a request to check
|
32
|
+
# @return [Boolean] true, if given request point to part of the API
|
33
|
+
def api?(req)
|
34
|
+
(req.path.start_with?('/api') || req.path.start_with?('/version.json'))
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# Sets logger level for database handlers
|
40
|
+
#
|
41
|
+
# @return [nil]
|
42
|
+
def setup_database_logger
|
43
|
+
if PuppetHerald.in_dev?
|
44
|
+
ActiveRecord::Base.logger.level = Logger::DEBUG
|
45
|
+
else
|
46
|
+
ActiveRecord::Base.logger.level = Logger::WARN
|
47
|
+
end
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
if PuppetHerald.in_dev?
|
53
|
+
set :environment, :development
|
54
|
+
else
|
55
|
+
set :environment, :production
|
56
|
+
end
|
57
|
+
set :show_exceptions, false
|
58
|
+
|
59
|
+
error do
|
60
|
+
@bug = PuppetHerald.bug env['sinatra.error']
|
61
|
+
if PuppetHerald::App::Configuration.api? request
|
62
|
+
content_type 'application/json'
|
63
|
+
@bug.to_json
|
64
|
+
else
|
65
|
+
erb :err500
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'puppet-herald'
|
2
|
+
require 'puppet-herald/javascript'
|
3
|
+
require 'sinatra/base'
|
4
|
+
require 'sinatra/namespace'
|
5
|
+
|
6
|
+
# A module for Herald
|
7
|
+
module PuppetHerald
|
8
|
+
# A module that holds module of app
|
9
|
+
module App
|
10
|
+
# Frontend logic impl internal class
|
11
|
+
class LogicImpl
|
12
|
+
def initialize
|
13
|
+
@js = PuppetHerald::Javascript.new
|
14
|
+
end
|
15
|
+
# Gets an app.html
|
16
|
+
# @dodgy executed also to raise an exception for testing (application_spec)
|
17
|
+
def app_html
|
18
|
+
if PuppetHerald.in_prod?
|
19
|
+
minified = '.min'
|
20
|
+
files = ['/app.min.js']
|
21
|
+
else
|
22
|
+
minified = ''
|
23
|
+
files = @js.files
|
24
|
+
end
|
25
|
+
[minified, files]
|
26
|
+
end
|
27
|
+
# Uglify an application JS's into one minified JS file
|
28
|
+
# @param mapname [String] name of source map to be put into uglified JS
|
29
|
+
# @return [Hash] a hash with uglified JS and source map
|
30
|
+
def uglify(mapname)
|
31
|
+
@js.uglify mapname
|
32
|
+
end
|
33
|
+
end
|
34
|
+
# Class that holds implementation of frontent interface
|
35
|
+
class Frontend < Sinatra::Base
|
36
|
+
use PuppetHerald::App::Configuration
|
37
|
+
set :logic, PuppetHerald::App::LogicImpl.new
|
38
|
+
|
39
|
+
get '/' do
|
40
|
+
redirect '/app.html', 301
|
41
|
+
end
|
42
|
+
|
43
|
+
get '/index.html' do
|
44
|
+
redirect '/app.html', 301
|
45
|
+
end
|
46
|
+
|
47
|
+
get '/app.html' do
|
48
|
+
cache_control :public, :must_revalidate, max_age: 60 if PuppetHerald.in_prod?
|
49
|
+
@minified, @files = settings.logic.app_html
|
50
|
+
erb :app
|
51
|
+
end
|
52
|
+
|
53
|
+
get(/\/app\.min\.(js\.map|js)/) do |ext|
|
54
|
+
content_type 'application/javascript'
|
55
|
+
contents = settings.logic.uglify('/app.min.js.map')[ext]
|
56
|
+
cache_control :public, :must_revalidate, max_age: 60 if PuppetHerald.in_prod?
|
57
|
+
contents
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -1,9 +1,6 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
|
-
|
3
|
-
|
4
|
-
<!--[if IE 8]> <html lang="en" ng-app="herald" class="no-js lt-ie9"> <![endif]-->
|
5
|
-
<!--[if gt IE 8]><!--> <html lang="en" ng-app="herald" class="no-js"> <!--<![endif]-->
|
6
|
-
<head ng-controller="AppController as app">
|
2
|
+
<html lang="en" ng-app="herald" ng-controller="AppController">
|
3
|
+
<head>
|
7
4
|
<meta charset="utf-8">
|
8
5
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
9
6
|
<title>Herald - a Puppet report processor</title>
|
@@ -20,7 +17,7 @@
|
|
20
17
|
|
21
18
|
<section class="container-fluid">
|
22
19
|
|
23
|
-
<h2><img src="/img/shield97.svg" />Herald <small>a Puppet report processor</small></h2>
|
20
|
+
<h2><a href="#/"><img src="/img/shield97.svg" />Herald</a> <small>a Puppet report processor</small></h2>
|
24
21
|
|
25
22
|
<div ng-view></div>
|
26
23
|
|
@@ -32,8 +29,8 @@
|
|
32
29
|
|
33
30
|
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular<%= @minified %>.js"></script>
|
34
31
|
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular-route<%= @minified %>.js"></script>
|
35
|
-
<script src="//cdn.jsdelivr.net/momentjs/2.
|
36
|
-
<script src="//cdn.jsdelivr.net/angular.moment/0.
|
32
|
+
<script src="//cdn.jsdelivr.net/momentjs/2.8.4/moment.min.js"></script>
|
33
|
+
<script src="//cdn.jsdelivr.net/angular.moment/0.8.3/angular-moment<%= @minified %>.js"></script>
|
37
34
|
|
38
35
|
<!-- Automatic incudes of project files -->
|
39
36
|
<% @files.each do |file| %>
|