minicron 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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>