minicron 0.1.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 (97) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +674 -0
  3. data/README.md +187 -0
  4. data/Rakefile +17 -0
  5. data/bin/minicron +26 -0
  6. data/lib/minicron.rb +179 -0
  7. data/lib/minicron/alert.rb +115 -0
  8. data/lib/minicron/alert/email.rb +50 -0
  9. data/lib/minicron/alert/pagerduty.rb +39 -0
  10. data/lib/minicron/alert/sms.rb +47 -0
  11. data/lib/minicron/cli.rb +367 -0
  12. data/lib/minicron/constants.rb +7 -0
  13. data/lib/minicron/cron.rb +192 -0
  14. data/lib/minicron/hub/app.rb +132 -0
  15. data/lib/minicron/hub/assets/app/application.js +151 -0
  16. data/lib/minicron/hub/assets/app/components/schedules.js +280 -0
  17. data/lib/minicron/hub/assets/app/controllers/executions.js +35 -0
  18. data/lib/minicron/hub/assets/app/controllers/hosts.js +129 -0
  19. data/lib/minicron/hub/assets/app/controllers/jobs.js +109 -0
  20. data/lib/minicron/hub/assets/app/controllers/schedules.js +80 -0
  21. data/lib/minicron/hub/assets/app/helpers.js +22 -0
  22. data/lib/minicron/hub/assets/app/models/execution.js +13 -0
  23. data/lib/minicron/hub/assets/app/models/host.js +15 -0
  24. data/lib/minicron/hub/assets/app/models/job.js +15 -0
  25. data/lib/minicron/hub/assets/app/models/job_execution_output.js +11 -0
  26. data/lib/minicron/hub/assets/app/models/schedule.js +32 -0
  27. data/lib/minicron/hub/assets/app/router.js +31 -0
  28. data/lib/minicron/hub/assets/app/routes/executions.js +36 -0
  29. data/lib/minicron/hub/assets/app/routes/hosts.js +42 -0
  30. data/lib/minicron/hub/assets/app/routes/index.js +9 -0
  31. data/lib/minicron/hub/assets/app/routes/jobs.js +52 -0
  32. data/lib/minicron/hub/assets/app/routes/schedules.js +37 -0
  33. data/lib/minicron/hub/assets/css/bootswatch.min.css +9 -0
  34. data/lib/minicron/hub/assets/css/main.scss +323 -0
  35. data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.eot +0 -0
  36. data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.svg +229 -0
  37. data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  38. data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  39. data/lib/minicron/hub/assets/fonts/lato-bold-700.woff +0 -0
  40. data/lib/minicron/hub/assets/fonts/lato-italic-400.woff +0 -0
  41. data/lib/minicron/hub/assets/fonts/lato-regular-400.woff +0 -0
  42. data/lib/minicron/hub/assets/js/ansi_up-1.1.1.min.js +6 -0
  43. data/lib/minicron/hub/assets/js/auth/ember-auth-9.0.7.min.js +2 -0
  44. data/lib/minicron/hub/assets/js/auth/ember-auth-request-jquery-1.0.3.min.js +1 -0
  45. data/lib/minicron/hub/assets/js/bootstrap-3.1.1.min.js +6 -0
  46. data/lib/minicron/hub/assets/js/ember-1.4.1.min.js +18 -0
  47. data/lib/minicron/hub/assets/js/ember-data-1.0.0-beta.7.f87cba88.min.js +10 -0
  48. data/lib/minicron/hub/assets/js/faye-browser-1.0.1.min.js +2 -0
  49. data/lib/minicron/hub/assets/js/handlebars-1.3.0.min.js +29 -0
  50. data/lib/minicron/hub/assets/js/jquery-2.1.0.min.js +4 -0
  51. data/lib/minicron/hub/assets/js/moment-2.5.1.min.js +7 -0
  52. data/lib/minicron/hub/controllers/api/executions.rb +34 -0
  53. data/lib/minicron/hub/controllers/api/hosts.rb +150 -0
  54. data/lib/minicron/hub/controllers/api/job_execution_outputs.rb +30 -0
  55. data/lib/minicron/hub/controllers/api/jobs.rb +118 -0
  56. data/lib/minicron/hub/controllers/api/schedule.rb +184 -0
  57. data/lib/minicron/hub/controllers/index.rb +5 -0
  58. data/lib/minicron/hub/db/schema.rb +98 -0
  59. data/lib/minicron/hub/db/schema.sql +158 -0
  60. data/lib/minicron/hub/models/alert.rb +7 -0
  61. data/lib/minicron/hub/models/execution.rb +8 -0
  62. data/lib/minicron/hub/models/host.rb +7 -0
  63. data/lib/minicron/hub/models/job.rb +18 -0
  64. data/lib/minicron/hub/models/job_execution_output.rb +7 -0
  65. data/lib/minicron/hub/models/schedule.rb +25 -0
  66. data/lib/minicron/hub/serializers/execution.rb +75 -0
  67. data/lib/minicron/hub/serializers/host.rb +57 -0
  68. data/lib/minicron/hub/serializers/job.rb +104 -0
  69. data/lib/minicron/hub/serializers/job_execution_output.rb +48 -0
  70. data/lib/minicron/hub/serializers/schedule.rb +68 -0
  71. data/lib/minicron/hub/views/handlebars/application.erb +51 -0
  72. data/lib/minicron/hub/views/handlebars/errors.erb +29 -0
  73. data/lib/minicron/hub/views/handlebars/executions.erb +79 -0
  74. data/lib/minicron/hub/views/handlebars/hosts.erb +205 -0
  75. data/lib/minicron/hub/views/handlebars/jobs.erb +203 -0
  76. data/lib/minicron/hub/views/handlebars/loading.erb +3 -0
  77. data/lib/minicron/hub/views/handlebars/schedules.erb +354 -0
  78. data/lib/minicron/hub/views/index.erb +7 -0
  79. data/lib/minicron/hub/views/layouts/app.erb +15 -0
  80. data/lib/minicron/monitor.rb +116 -0
  81. data/lib/minicron/transport.rb +15 -0
  82. data/lib/minicron/transport/client.rb +80 -0
  83. data/lib/minicron/transport/faye/client.rb +103 -0
  84. data/lib/minicron/transport/faye/extensions/job_handler.rb +184 -0
  85. data/lib/minicron/transport/faye/server.rb +58 -0
  86. data/lib/minicron/transport/server.rb +62 -0
  87. data/lib/minicron/transport/ssh.rb +51 -0
  88. data/spec/invalid_config.toml +2 -0
  89. data/spec/minicron/cli_spec.rb +154 -0
  90. data/spec/minicron/transport/client_spec.rb +8 -0
  91. data/spec/minicron/transport/faye/client_spec.rb +53 -0
  92. data/spec/minicron/transport/server_spec.rb +70 -0
  93. data/spec/minicron/transport_spec.rb +13 -0
  94. data/spec/minicron_spec.rb +133 -0
  95. data/spec/spec_helper.rb +33 -0
  96. data/spec/valid_config.toml +48 -0
  97. metadata +577 -0
@@ -0,0 +1,7 @@
1
+ module Minicron
2
+ module Hub
3
+ class Alert < ActiveRecord::Base
4
+ belongs_to :schedule
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Minicron
2
+ module Hub
3
+ class Execution < ActiveRecord::Base
4
+ belongs_to :job
5
+ has_many :job_execution_outputs, :dependent => :delete_all
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ module Minicron
2
+ module Hub
3
+ class Host < ActiveRecord::Base
4
+ has_many :jobs, :dependent => :delete_all
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ module Minicron
2
+ module Hub
3
+ class Job < ActiveRecord::Base
4
+ belongs_to :host
5
+ has_many :executions, :dependent => :delete_all
6
+ has_many :schedules, :dependent => :delete_all
7
+
8
+ # Default the name of the command to the command itself if no name is set
9
+ def name
10
+ if read_attribute(:name) == '' || read_attribute(:name) == nil
11
+ read_attribute(:command)
12
+ else
13
+ read_attribute(:name)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ module Minicron
2
+ module Hub
3
+ class JobExecutionOutput < ActiveRecord::Base
4
+ belongs_to :execution
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ module Minicron
2
+ module Hub
3
+ class Schedule < ActiveRecord::Base
4
+ belongs_to :job
5
+
6
+ # The formatted schedule
7
+ def formatted
8
+ Minicron::Hub::Schedule.format(self)
9
+ end
10
+
11
+ # Format the schedule based on all it's components
12
+ #
13
+ # @param schedule [Minicron::Hub::Schedule]
14
+ # @return string
15
+ def self.format(schedule)
16
+ # If it's not a 'special' schedule then build up the full schedule string
17
+ if schedule.special == '' || schedule.special == nil
18
+ "#{schedule.minute} #{schedule.hour} #{schedule.day_of_the_month} #{schedule.month} #{schedule.day_of_the_week}"
19
+ else
20
+ schedule.special
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,75 @@
1
+ class Minicron::Hub::App::ExecutionSerializer
2
+ def initialize(executions)
3
+ @executions = executions
4
+ end
5
+
6
+ def serialize
7
+ @response = {
8
+ :executions => [],
9
+ :jobs => [],
10
+ :job_execution_outputs => [],
11
+ :hosts => []
12
+ }
13
+
14
+ if @executions.respond_to? :each
15
+ @executions.each do |execution|
16
+ do_serialization(execution)
17
+ end
18
+ else
19
+ do_serialization(@executions)
20
+ end
21
+
22
+ @response
23
+ end
24
+
25
+ def do_serialization(execution)
26
+ new_execution = {}
27
+
28
+ # Add all the normal attributes of the execution
29
+ execution.attributes.each do |key, value|
30
+ # Remove _id from keys
31
+ key = key[-3, 3] == '_id' ? key[0..-4] : key
32
+
33
+ new_execution[key] = value
34
+ end
35
+
36
+ # Set up the job execution output ids array
37
+ new_execution[:job_execution_outputs] = []
38
+
39
+ # Add the job to the sideloaded data
40
+ new_job = {}
41
+ execution.job.attributes.each do |key, value|
42
+ # To make our name method in the model work :/
43
+ value = execution.job.name if key == 'name'
44
+
45
+ # Remove _id from keys
46
+ key = key[-3, 3] == '_id' ? key[0..-4] : key
47
+
48
+ new_job[key] = value
49
+ end
50
+
51
+ # Append the new job to the @response
52
+ @response[:jobs].push(new_job)
53
+
54
+ # Append the job host to the @response
55
+ @response[:hosts].push(execution.job.host)
56
+
57
+ # Add the job execution outputs to the sideloaded data and the ids to
58
+ # the execution
59
+ execution.job_execution_outputs.each do |job_execution_output|
60
+ new_job_execution_output = {}
61
+
62
+ job_execution_output.attributes.each do |key, value|
63
+ # Remove _id from keys
64
+ key = key[-3, 3] == '_id' ? key[0..-4] : key
65
+ new_job_execution_output[key] = value
66
+ end
67
+
68
+ @response[:job_execution_outputs].push(new_job_execution_output)
69
+ new_execution[:job_execution_outputs].push(job_execution_output.id)
70
+ end
71
+
72
+ # Append the new execution to the @response
73
+ @response[:executions].push(new_execution)
74
+ end
75
+ end
@@ -0,0 +1,57 @@
1
+ class Minicron::Hub::App::HostSerializer
2
+ def initialize(hosts)
3
+ @hosts = hosts
4
+ end
5
+
6
+ def serialize
7
+ @response = {
8
+ :hosts => [],
9
+ :jobs => []
10
+ }
11
+
12
+ if @hosts.respond_to? :each
13
+ @hosts.each do |host|
14
+ do_serialization(host)
15
+ end
16
+ else
17
+ do_serialization(@hosts)
18
+ end
19
+
20
+ @response
21
+ end
22
+
23
+ def do_serialization(host)
24
+ new_host = {}
25
+
26
+ # Add all the normal attributes of the host
27
+ host.attributes.each do |key, value|
28
+ new_host[key] = value
29
+ end
30
+
31
+ # Set up the job host output ids array
32
+ new_host[:jobs] = []
33
+
34
+ # Add the jobs to the sideloaded data and the ids to
35
+ # the host
36
+ host.jobs.each do |job|
37
+ new_job = {}
38
+
39
+ job.attributes.each do |key, value|
40
+ # To make our name method in the model work :/
41
+ value = job.name if key == 'name'
42
+
43
+ # Remove _id from keys
44
+ key = key[-3, 3] == '_id' ? key[0..-4] : key
45
+
46
+ # Append the job
47
+ new_job[key] = value
48
+ end
49
+
50
+ @response[:jobs].push(new_job)
51
+ new_host[:jobs].push(job.id)
52
+ end
53
+
54
+ # Append the new host to the @responseh
55
+ @response[:hosts].push(new_host)
56
+ end
57
+ end
@@ -0,0 +1,104 @@
1
+ class Minicron::Hub::App::JobSerializer
2
+ def initialize(jobs)
3
+ @jobs = jobs
4
+ end
5
+
6
+ def serialize
7
+ @response = {
8
+ :jobs => [],
9
+ :hosts => [],
10
+ :executions => [],
11
+ :schedules => []
12
+ }
13
+
14
+ if @jobs.respond_to? :each
15
+ @jobs.each do |job|
16
+ do_serialization(job)
17
+ end
18
+ else
19
+ do_serialization(@jobs)
20
+ end
21
+
22
+ @response
23
+ end
24
+
25
+ def do_serialization(job)
26
+ new_job = {}
27
+
28
+ # Add all the normal attributes of the job
29
+ job.attributes.each do |key, value|
30
+ # To make our name method in the model work :/
31
+ value = job.name if key == 'name'
32
+
33
+ # Remove _id from keys
34
+ key = key[-3, 3] == '_id' ? key[0..-4] : key
35
+
36
+ new_job[key] = value
37
+ end
38
+
39
+ # Set up the execution ids array
40
+ new_job[:executions] = []
41
+
42
+ # Set up the schedules ids array
43
+ new_job[:schedules] = []
44
+
45
+ # Add the host to the sideloaded data
46
+ new_host = {}
47
+ job.host.attributes.each do |key, value|
48
+ # To make our name method in the model work :/
49
+ value = job.host.name if key == 'name'
50
+
51
+ # Remove _id from keys
52
+ key = key[-3, 3] == '_id' ? key[0..-4] : key
53
+
54
+ new_host[key] = value
55
+ end
56
+
57
+ # Append the new host to the @response
58
+ @response[:hosts].push(new_host)
59
+
60
+ # Add the schedules to the sideloaded data and the ids to
61
+ # the job
62
+ job.schedules.each do |schedule|
63
+ new_schedule = {}
64
+
65
+ schedule.attributes.each do |key, value|
66
+ # Remove _id from keys
67
+ key = key[-3, 3] == '_id' ? key[0..-4] : key
68
+
69
+ new_schedule[key] = value
70
+ end
71
+
72
+ # Add the formatted version of the schedule
73
+ new_schedule['formatted'] = schedule.formatted
74
+
75
+ @response[:schedules].push(new_schedule)
76
+ new_job[:schedules].push(schedule.id)
77
+ end
78
+
79
+ # Add the executions to the sideloaded data and the ids to
80
+ # the job
81
+ job.executions.each do |execution|
82
+ new_execution = {}
83
+
84
+ execution.attributes.each do |key, value|
85
+ # Remove _id from keys
86
+ key = key[-3, 3] == '_id' ? key[0..-4] : key
87
+
88
+ new_execution[key] = value
89
+ end
90
+
91
+ # Also we need to add the job execution output ids
92
+ new_execution[:job_execution_outputs] = []
93
+ execution.job_execution_outputs.each do |job_execution_output|
94
+ new_execution[:job_execution_outputs].push(job_execution_output.id)
95
+ end
96
+
97
+ @response[:executions].push(new_execution)
98
+ new_job[:executions].push(execution.id)
99
+ end
100
+
101
+ # Append the new job to the @responseh
102
+ @response[:jobs].push(new_job)
103
+ end
104
+ end
@@ -0,0 +1,48 @@
1
+ class Minicron::Hub::App::JobExecutionOutputSerializer
2
+ def initialize(job_execution_outputs)
3
+ @job_execution_outputs = job_execution_outputs
4
+ end
5
+
6
+ def serialize
7
+ @response = {
8
+ :job_execution_outputs => [],
9
+ :executions => []
10
+ }
11
+
12
+ if @job_execution_outputs.respond_to? :each
13
+ @job_execution_outputs.each do |job_execution_output|
14
+ do_serialization(job_execution_output)
15
+ end
16
+ else
17
+ do_serialization(@job_execution_outputs)
18
+ end
19
+
20
+ @response
21
+ end
22
+
23
+ def do_serialization(job_execution_output)
24
+ new_job_execution_output = {}
25
+
26
+ # Add all the normal attributes of the job_execution_output
27
+ job_execution_output.attributes.each do |key, value|
28
+ # Remove _id from keys
29
+ key = key[-3, 3] == '_id' ? key[0..-4] : key
30
+ new_job_execution_output[key] = value
31
+ end
32
+
33
+ # Add the execution to the sideloaded data
34
+ new_execution = {}
35
+ job_execution_output.execution.attributes.each do |key, value|
36
+ # Remove _id from keys
37
+ key = key[-3, 3] == '_id' ? key[0..-4] : key
38
+
39
+ new_execution[key] = value
40
+ end
41
+
42
+ # Append the new execution to the @response
43
+ @response[:executions].push(new_execution)
44
+
45
+ # Append the new job_execution_output to the @response
46
+ @response[:job_execution_outputs].push(new_job_execution_output)
47
+ end
48
+ end
@@ -0,0 +1,68 @@
1
+ class Minicron::Hub::App::ScheduleSerializer
2
+ def initialize(schedules)
3
+ @schedules = schedules
4
+ end
5
+
6
+ def serialize
7
+ @response = {
8
+ :schedules => [],
9
+ :jobs => []
10
+ }
11
+
12
+ if @schedules.respond_to? :each
13
+ @schedules.each do |schedule|
14
+ do_serialization(schedule)
15
+ end
16
+ else
17
+ do_serialization(@schedules)
18
+ end
19
+
20
+ @response
21
+ end
22
+
23
+ def do_serialization(schedule)
24
+ new_schedule = {}
25
+
26
+ # Add all the normal attributes of the schedule
27
+ schedule.attributes.each do |key, value|
28
+ # Remove _id from keys
29
+ key = key[-3, 3] == '_id' ? key[0..-4] : key
30
+
31
+ new_schedule[key] = value
32
+ end
33
+
34
+ # Add the formatted version of the schedule
35
+ new_schedule['formatted'] = schedule.formatted
36
+
37
+ # Add the schedule job to the sideloaded data
38
+ new_job = {
39
+ :schedules => [],
40
+ :executions => []
41
+ }
42
+ schedule.job.attributes.each do |key, value|
43
+ # To make our name method in the model work :/
44
+ value = schedule.job.name if key == 'name'
45
+
46
+ # Remove _id from keys
47
+ key = key[-3, 3] == '_id' ? key[0..-4] : key
48
+
49
+ new_job[key] = value
50
+ end
51
+
52
+ # Add the ids of each job schedule to the job
53
+ schedule.job.schedules.each do |s|
54
+ new_job[:schedules].push(s.id)
55
+ end
56
+
57
+ # Add the ids of each job execution to the job
58
+ schedule.job.executions.each do |execution|
59
+ new_job[:executions].push(execution.id)
60
+ end
61
+
62
+ # Append the new job to the @response
63
+ @response[:jobs].push(new_job)
64
+
65
+ # Append the new schedule to the @responseh
66
+ @response[:schedules].push(new_schedule)
67
+ end
68
+ end
@@ -0,0 +1,51 @@
1
+ <script type="text/x-handlebars">
2
+ <div class="navbar navbar-default navbar-fixed-top" role="navigation">
3
+ <div class="main-container">
4
+ <div class="navbar-header">
5
+ {{#link-to 'index' class="navbar-brand"}}minicron{{/link-to}}
6
+ </div>
7
+
8
+ <ul class="nav navbar-nav">
9
+ {{#link-to 'executions' tagName='li' href=false}}<a {{bind-attr href='view.href'}}>Executions</a>{{/link-to}}
10
+ {{#link-to 'jobs' tagName='li' href=false}}<a {{bind-attr href='view.href'}}>Jobs</a>{{/link-to}}
11
+ {{#link-to 'hosts' tagName='li' href=false}}<a {{bind-attr href='view.href'}}>Hosts</a>{{/link-to}}
12
+ </ul>
13
+ </div>
14
+ </div>
15
+
16
+ <div class="main-container clearfix">
17
+ <div class="sidebar">
18
+ <h2>Recent Job Executions</h2>
19
+ <div class="list-group">
20
+ {{#each controller.sortedExecutions}}
21
+ {{#link-to 'execution' id class="list-group-item clearfix"}}
22
+ <span class="pull-left">{{job.name}}</span>
23
+ {{#if exit_status}}
24
+ <span class="pull-right execution-status label label-danger" data-toggle="tooltip" data-placement="right" title="Failed">
25
+ <span class="glyphicon glyphicon-remove"></span>
26
+ </span>
27
+ {{else}}
28
+ {{#if finished_at}}
29
+ <span class="pull-right execution-status label label-success" data-toggle="tooltip" data-placement="right" title="Successful">
30
+ <span class="glyphicon glyphicon-ok"></span>
31
+ </span>
32
+ {{else}}
33
+ <span class="pull-right execution-status label label-warning" data-toggle="tooltip" data-placement="right" title="Running">
34
+ <span class="glyphicon glyphicon-flash"></span>
35
+ </span>
36
+ {{/if}}
37
+ {{/if}}
38
+ <div style="clear: left;"></div>
39
+ <span class="execution-info">{{time_ago created_at}} on {{job.host.name}}</span>
40
+ {{/link-to}}
41
+ {{/each}}
42
+ </div>
43
+ </div>
44
+
45
+ <div class="main-panel">
46
+ <div class="inner">
47
+ {{outlet}}
48
+ </div>
49
+ </div>
50
+ </div>
51
+ </script>