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.
Files changed (65) hide show
  1. checksums.yaml +15 -7
  2. data/.rubocop.yml +31 -0
  3. data/.rubocop_todo.yml +6 -0
  4. data/.travis.yml +7 -7
  5. data/Gemfile +5 -9
  6. data/README.md +152 -16
  7. data/Rakefile +67 -6
  8. data/bin/puppet-herald +1 -1
  9. data/config.ru +2 -2
  10. data/db/migrate/20141211165540_create_nodes.rb +5 -3
  11. data/db/migrate/20141211171305_create_reports.rb +12 -10
  12. data/db/migrate/20141211171326_create_log_entries.rb +9 -7
  13. data/db/schema.rb +24 -26
  14. data/lib/puppet-herald.rb +59 -21
  15. data/lib/puppet-herald/app/api.rb +111 -0
  16. data/lib/puppet-herald/app/configuration.rb +70 -0
  17. data/lib/puppet-herald/app/frontend.rb +61 -0
  18. data/lib/puppet-herald/{views → app/views}/app.erb +5 -8
  19. data/lib/puppet-herald/{views → app/views}/err500.erb +1 -4
  20. data/lib/puppet-herald/application.rb +27 -0
  21. data/lib/puppet-herald/cli.rb +66 -45
  22. data/lib/puppet-herald/client.rb +33 -0
  23. data/lib/puppet-herald/database.rb +84 -40
  24. data/lib/puppet-herald/javascript.rb +23 -17
  25. data/lib/puppet-herald/models/log-entry.rb +10 -3
  26. data/lib/puppet-herald/models/node.rb +15 -5
  27. data/lib/puppet-herald/models/report.rb +70 -63
  28. data/lib/puppet-herald/public/app.js +9 -8
  29. data/lib/puppet-herald/public/components/directives/status-button.html +1 -1
  30. data/lib/puppet-herald/public/components/directives/status-button.js +5 -3
  31. data/lib/puppet-herald/public/components/filters/filters.js +9 -4
  32. data/lib/puppet-herald/public/components/page.js +34 -0
  33. data/lib/puppet-herald/public/node/node.html +3 -1
  34. data/lib/puppet-herald/public/node/node.js +7 -4
  35. data/lib/puppet-herald/public/nodes/nodes.js +3 -2
  36. data/lib/puppet-herald/public/report/report.html +4 -1
  37. data/lib/puppet-herald/public/report/report.js +5 -3
  38. data/lib/puppet-herald/stubs/puppet.rb +20 -9
  39. data/lib/puppet-herald/version.rb +17 -7
  40. data/package.json +8 -3
  41. data/puppet-herald.gemspec +3 -6
  42. data/spec/integration/application_spec.rb +175 -0
  43. data/spec/integration/models/node_spec.rb +4 -4
  44. data/spec/integration/models/report_spec.rb +7 -7
  45. data/spec/spec_helper.rb +12 -7
  46. data/spec/support/active_record.rb +6 -10
  47. data/spec/support/reconnectdb.rb +13 -0
  48. data/spec/unit/puppet-herald/cli_spec.rb +45 -13
  49. data/spec/unit/puppet-herald/client_spec.rb +23 -0
  50. data/spec/unit/puppet-herald/database_spec.rb +8 -9
  51. data/spec/unit/puppet-herald/javascript_spec.rb +8 -13
  52. data/spec/unit/puppet-herald_spec.rb +4 -4
  53. data/test/javascript/karma.conf.js +43 -5
  54. data/test/javascript/src/app_test.js +90 -0
  55. data/test/javascript/src/components/artifact/artifact-directive_test.js +36 -0
  56. data/test/javascript/src/components/artifact/artifact_test.js +64 -0
  57. data/test/javascript/src/components/directives/status-button_test.js +159 -0
  58. data/test/javascript/src/components/filters/filters_test.js +35 -0
  59. data/test/javascript/src/node/node_test.js +87 -0
  60. data/test/javascript/src/nodes/nodes_test.js +56 -0
  61. data/test/javascript/src/report/report_test.js +94 -0
  62. metadata +98 -68
  63. data/lib/puppet-herald/app.rb +0 -103
  64. data/lib/puppet-herald/public/components/artifact/artifact-directive_test.js +0 -17
  65. 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 :time
5
- t.string :level
6
- t.string :source
7
- t.integer :line
8
- t.text :message
9
-
10
- t.references :report
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: 20141211171326) do
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 "plpgsql"
16
+ enable_extension 'plpgsql'
18
17
 
19
- create_table "log_entries", force: true do |t|
20
- t.datetime "time"
21
- t.string "level"
22
- t.string "source"
23
- t.integer "line"
24
- t.text "message"
25
- t.integer "report_id"
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 "nodes", force: true do |t|
29
- t.string "name"
30
- t.string "status"
31
- t.integer "no_of_reports"
32
- t.datetime "last_run"
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 "reports", force: true do |t|
36
- t.string "status"
37
- t.string "environment"
38
- t.string "transaction_uuid"
39
- t.string "configuration_version"
40
- t.string "puppet_version"
41
- t.string "kind"
42
- t.string "host"
43
- t.datetime "time"
44
- t.integer "node_id"
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
- @@root = File.dirname(File.dirname(File.realpath(__FILE__)))
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
- def self.relative_dir dir
12
- File.realpath(File.join @@root, dir)
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
- env = ENV['PUPPET_HERALD_ENV'].to_sym
19
- end
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
- def self.is_in_dev?
24
- return [:development, :dev, :test, :ci].include? environment
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
- def self.is_in_prod?
28
- return !is_in_dev?
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
- def self.bug ex
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.to_s}: #{ex.message}"
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
- :message => message,
41
- :homepage => PuppetHerald::HOMEPAGE,
42
- :bugfile => filepath,
43
- :help => "Please report this bug to #{PuppetHerald::HOMEPAGE} by passing contents of bug file: #{filepath}"
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
- return bugo
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
- <!--[if lt IE 7]> <html lang="en" ng-app="herald" class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
3
- <!--[if IE 7]> <html lang="en" ng-app="herald" class="no-js lt-ie9 lt-ie8"> <![endif]-->
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.5.1/moment.min.js"></script>
36
- <script src="//cdn.jsdelivr.net/angular.moment/0.6.2/angular-moment.js"></script>
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| %>