rocketjob_mission_control 0.9.2

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 (81) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +26 -0
  4. data/app/assets/javascripts/rocket_job_mission_control/application.js +18 -0
  5. data/app/assets/javascripts/rocket_job_mission_control/base.js.coffee +24 -0
  6. data/app/assets/javascripts/rocket_job_mission_control/jobs.js.coffee +11 -0
  7. data/app/assets/stylesheets/rocket_job_mission_control/application.scss +18 -0
  8. data/app/assets/stylesheets/rocket_job_mission_control/base.scss +468 -0
  9. data/app/assets/stylesheets/rocket_job_mission_control/bootstrap_and_overrides.scss +6 -0
  10. data/app/assets/stylesheets/rocket_job_mission_control/callout.scss +40 -0
  11. data/app/assets/stylesheets/rocket_job_mission_control/jobs.scss +16 -0
  12. data/app/assets/stylesheets/rocket_job_mission_control/jquery.bootstrap-touchspin.scss +45 -0
  13. data/app/controllers/rocket_job_mission_control/application_controller.rb +15 -0
  14. data/app/controllers/rocket_job_mission_control/jobs/inputs_controller.rb +9 -0
  15. data/app/controllers/rocket_job_mission_control/jobs/slices_controller.rb +10 -0
  16. data/app/controllers/rocket_job_mission_control/jobs_controller.rb +97 -0
  17. data/app/controllers/rocket_job_mission_control/workers_controller.rb +79 -0
  18. data/app/helpers/rocket_job_mission_control/application_helper.rb +16 -0
  19. data/app/helpers/rocket_job_mission_control/jobs_helper.rb +57 -0
  20. data/app/helpers/rocket_job_mission_control/workers_helper.rb +14 -0
  21. data/app/views/layouts/rocket_job_mission_control/application.html.haml +43 -0
  22. data/app/views/layouts/rocket_job_mission_control/partials/_header.html.haml +16 -0
  23. data/app/views/layouts/rocket_job_mission_control/partials/_sidebar.html.haml +20 -0
  24. data/app/views/rocket_job_mission_control/jobs/_list.html.haml +33 -0
  25. data/app/views/rocket_job_mission_control/jobs/_status.html.haml +39 -0
  26. data/app/views/rocket_job_mission_control/jobs/index.html.haml +8 -0
  27. data/app/views/rocket_job_mission_control/jobs/running.html.haml +37 -0
  28. data/app/views/rocket_job_mission_control/jobs/show.html.haml +50 -0
  29. data/app/views/rocket_job_mission_control/workers/_actions.html.haml +9 -0
  30. data/app/views/rocket_job_mission_control/workers/index.html.haml +51 -0
  31. data/config/locales/en.yml +57 -0
  32. data/config/routes.rb +28 -0
  33. data/lib/rocket_job_mission_control/engine.rb +15 -0
  34. data/lib/rocket_job_mission_control/version.rb +3 -0
  35. data/lib/rocketjob_mission_control.rb +4 -0
  36. data/lib/tasks/rocket_job_mission_control_tasks.rake +4 -0
  37. data/spec/controllers/application_controller_spec.rb +47 -0
  38. data/spec/controllers/jobs_controller_spec.rb +217 -0
  39. data/spec/controllers/workers_controller_spec.rb +125 -0
  40. data/spec/dummy/README.rdoc +28 -0
  41. data/spec/dummy/Rakefile +6 -0
  42. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  43. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  44. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  45. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  46. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  47. data/spec/dummy/bin/bundle +3 -0
  48. data/spec/dummy/bin/rails +4 -0
  49. data/spec/dummy/bin/rake +4 -0
  50. data/spec/dummy/config.ru +4 -0
  51. data/spec/dummy/config/application.rb +25 -0
  52. data/spec/dummy/config/boot.rb +5 -0
  53. data/spec/dummy/config/database.yml +25 -0
  54. data/spec/dummy/config/environment.rb +5 -0
  55. data/spec/dummy/config/environments/development.rb +34 -0
  56. data/spec/dummy/config/environments/test.rb +39 -0
  57. data/spec/dummy/config/initializers/assets.rb +8 -0
  58. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  59. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  60. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  61. data/spec/dummy/config/initializers/inflections.rb +16 -0
  62. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  63. data/spec/dummy/config/initializers/session_store.rb +3 -0
  64. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  65. data/spec/dummy/config/locales/en.yml +23 -0
  66. data/spec/dummy/config/routes.rb +4 -0
  67. data/spec/dummy/config/secrets.yml +22 -0
  68. data/spec/dummy/log/test.log +2459 -0
  69. data/spec/dummy/public/404.html +67 -0
  70. data/spec/dummy/public/422.html +67 -0
  71. data/spec/dummy/public/500.html +66 -0
  72. data/spec/dummy/public/favicon.ico +0 -0
  73. data/spec/helpers/jobs_helper_spec.rb +100 -0
  74. data/spec/rails_helper.rb +47 -0
  75. data/spec/spec_helper.rb +81 -0
  76. data/spec/views/workers/index.html.haml_spec.rb +17 -0
  77. data/vendor/assets/javascripts/jquery.bootstrap-touchspin.js +686 -0
  78. data/vendor/assets/javascripts/prism.js +6 -0
  79. data/vendor/assets/stylesheets/jquery.bootstrap-touchspin.css +45 -0
  80. data/vendor/assets/stylesheets/prism.scss +160 -0
  81. metadata +319 -0
@@ -0,0 +1,6 @@
1
+ @import "bootstrap-sprockets";
2
+ @import "bootstrap";
3
+
4
+ .alert-notice {
5
+ @extend .alert-info
6
+ }
@@ -0,0 +1,40 @@
1
+ .callout {
2
+ border: 1px solid #eee;
3
+ border-left-width: 0.5em;
4
+ }
5
+
6
+ .callout-top {
7
+ border: 1px solid #eee;
8
+ border-top-width: 5px;
9
+ }
10
+
11
+ .callout-info-top {
12
+ border-top-color: #1b809e;
13
+ }
14
+
15
+ .callout-success-top {
16
+ border-top-color: #3c763d;
17
+ }
18
+
19
+ .callout-warning-top {
20
+ border-top-color: #aa6708;
21
+ }
22
+
23
+ .callout-alert-top {
24
+ border-top-color: #ce4844;
25
+ }
26
+ .callout-info {
27
+ border-left-color: #1b809e;
28
+ }
29
+
30
+ .callout-success {
31
+ border-left-color: #3c763d;
32
+ }
33
+
34
+ .callout-warning {
35
+ border-left-color: #aa6708;
36
+ }
37
+
38
+ .callout-alert {
39
+ border-left-color: #ce4844;
40
+ }
@@ -0,0 +1,16 @@
1
+ .job-list {
2
+ .list {
3
+ .progress {
4
+ width: 16em;
5
+ height: 1em;
6
+ margin: 5px 0px 0px 10px;
7
+ -webkit-border-radius: 0 !important;
8
+ -moz-border-radius: 0 !important;
9
+ border-radius: 0 !important;
10
+ }
11
+
12
+ .progress-bar {
13
+ min-width: 1em;
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,45 @@
1
+ /*
2
+ * Bootstrap TouchSpin - v3.0.1
3
+ * A mobile and touch friendly input spinner component for Bootstrap 3.
4
+ * http://www.virtuosoft.eu/code/bootstrap-touchspin/
5
+ *
6
+ * Made by István Ujj-Mészáros
7
+ * Under Apache License v2.0 License
8
+ */
9
+
10
+ .bootstrap-touchspin .input-group-btn-vertical {
11
+ position: relative;
12
+ white-space: nowrap;
13
+ width: 1%;
14
+ vertical-align: middle;
15
+ display: table-cell;
16
+ }
17
+
18
+ .bootstrap-touchspin .input-group-btn-vertical > .btn {
19
+ display: block;
20
+ float: none;
21
+ width: 100%;
22
+ max-width: 100%;
23
+ padding: 8px 10px;
24
+ margin-left: -1px;
25
+ position: relative;
26
+ }
27
+
28
+ .bootstrap-touchspin .input-group-btn-vertical .bootstrap-touchspin-up {
29
+ border-radius: 0;
30
+ border-top-right-radius: 4px;
31
+ }
32
+
33
+ .bootstrap-touchspin .input-group-btn-vertical .bootstrap-touchspin-down {
34
+ margin-top: -2px;
35
+ border-radius: 0;
36
+ border-bottom-right-radius: 4px;
37
+ }
38
+
39
+ .bootstrap-touchspin .input-group-btn-vertical i {
40
+ position: absolute;
41
+ top: 3px;
42
+ left: 5px;
43
+ font-size: 9px;
44
+ font-weight: normal;
45
+ }
@@ -0,0 +1,15 @@
1
+ module RocketJobMissionControl
2
+ class ApplicationController < ActionController::Base
3
+ include ActionController::Live
4
+
5
+ around_action :with_time_zone
6
+
7
+ private
8
+
9
+ def with_time_zone
10
+ if time_zone = session['time_zone'] || 'UTC'
11
+ Time.use_zone(time_zone) { yield }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module RocketJobMissionControl
2
+ module Jobs
3
+ class SlicesController < RocketJobMissionControl::ApplicationController
4
+ def index
5
+
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ module RocketJobMissionControl
2
+ module Jobs
3
+ class InputsController < RocketJobMissionControl::ApplicationController
4
+ def index
5
+ @job = RocketJob::Job.find(params[:id])
6
+ @inputs = @job.inputs
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,97 @@
1
+ module RocketJobMissionControl
2
+ class JobsController < RocketJobMissionControl::ApplicationController
3
+ before_filter :find_job_or_redirect, except: [:index, :running]
4
+ rescue_from StandardError, with: :error_occurred
5
+
6
+ def running
7
+ @jobs = RocketJob::Job.where(state: 'running')
8
+ end
9
+
10
+ def update
11
+ @job.update_attributes!(job_params)
12
+
13
+ redirect_to job_path(@job)
14
+ end
15
+
16
+ def abort
17
+ @job.abort!
18
+
19
+ redirect_to(job_path(@job))
20
+ end
21
+
22
+ def destroy
23
+ if @job.completed? || @job.aborted?
24
+ @job.destroy
25
+ redirect_to(jobs_path)
26
+ else
27
+ flash[:alert] = "Cannot destroy a job unless it is completed or aborted"
28
+ redirect_to(job_path(@job))
29
+ end
30
+ end
31
+
32
+ def retry
33
+ @job.retry!
34
+
35
+ redirect_to(job_path(@job))
36
+ end
37
+
38
+ def pause
39
+ @job.pause!
40
+
41
+ redirect_to(job_path(@job))
42
+ end
43
+
44
+ def resume
45
+ @job.resume!
46
+
47
+ redirect_to(job_path(@job))
48
+ end
49
+
50
+ def fail
51
+ @job.fail!
52
+
53
+ redirect_to(job_path(@job))
54
+ end
55
+
56
+ def show
57
+ load_jobs
58
+ end
59
+
60
+ def index
61
+ load_jobs
62
+ end
63
+
64
+ private
65
+
66
+ def load_jobs
67
+ @states = jobs_params
68
+ @jobs = RocketJob::Job.limit(1000).sort(created_at: :desc)
69
+ @jobs = @jobs.where(state: @states) unless @states.empty?
70
+ end
71
+
72
+ def find_job_or_redirect
73
+ @job = RocketJob::Job.find(params[:id])
74
+
75
+ if @job.nil?
76
+ flash[:alert] = t(:failure, scope: [:job, :find], id: params[:id])
77
+
78
+ redirect_to(jobs_path)
79
+ end
80
+ end
81
+
82
+ def jobs_params
83
+ params.fetch(:states, [])
84
+ end
85
+
86
+ def job_params
87
+ params.require(:job).permit(:priority)
88
+ end
89
+
90
+ def error_occurred(exception)
91
+ logger.error "Error loading a job", exception
92
+ flash[:danger] = "Error loading jobs."
93
+ raise exception if Rails.env.development?
94
+ redirect_to :back
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,79 @@
1
+ module RocketJobMissionControl
2
+ class WorkersController < RocketJobMissionControl::ApplicationController
3
+ before_filter :find_worker, only: [:stop, :pause, :resume, :destroy]
4
+
5
+ def index
6
+ @workers = RocketJob::Worker.sort(:name)
7
+ end
8
+
9
+ VALID_STATES = { stop: 'stopped', pause: 'paused', resume: 'resumed' }
10
+
11
+ def update_all
12
+ worker_action = params[:worker_action].to_sym
13
+ if VALID_STATES.keys.include?(worker_action)
14
+ RocketJob::Worker.send("#{worker_action}_all".to_sym)
15
+ flash[:notice] = t(:success, scope: [:worker, :update_all], worker_action: VALID_STATES[worker_action])
16
+ else
17
+ flash[:alert] = t(:invalid, scope: [:worker, :update_all])
18
+ end
19
+
20
+ respond_to do |format|
21
+ format.html { redirect_to workers_path }
22
+ end
23
+ end
24
+
25
+ def stop
26
+ if @worker.stop!
27
+ flash[:notice] = t(:success, scope: [:worker, :stop])
28
+ else
29
+ flash[:alert] = t(:failure, scope: [:worker, :stop])
30
+ end
31
+
32
+ respond_to do |format|
33
+ format.html { redirect_to workers_path }
34
+ end
35
+ end
36
+
37
+ def destroy
38
+ if @worker.destroy
39
+ flash[:notice] = t(:success, scope: [:worker, :destroy])
40
+ else
41
+ flash[:alert] = t(:failure, scope: [:worker, :destroy])
42
+ end
43
+
44
+ respond_to do |format|
45
+ format.html { redirect_to workers_path }
46
+ end
47
+ end
48
+
49
+ def pause
50
+ if @worker.pause!
51
+ flash[:notice] = t(:success, scope: [:worker, :pause])
52
+ else
53
+ flash[:alert] = t(:failure, scope: [:worker, :pause])
54
+ end
55
+
56
+ respond_to do |format|
57
+ format.html { redirect_to workers_path }
58
+ end
59
+ end
60
+
61
+ def resume
62
+ if @worker.resume!
63
+ flash[:notice] = t(:success, scope: [:worker, :resume])
64
+ else
65
+ flash[:alert] = t(:failure, scope: [:worker, :resume])
66
+ end
67
+
68
+ respond_to do |format|
69
+ format.html { redirect_to workers_path }
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def find_worker
76
+ @worker = RocketJob::Worker.find(params[:id])
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,16 @@
1
+ module RocketJobMissionControl
2
+ module ApplicationHelper
3
+ def site_title
4
+ 'Rocket Job Mission Control'
5
+ end
6
+
7
+ def title
8
+ @page_title ||= params[:controller].to_s.titleize
9
+ h(@full_title || [@page_title, site_title].compact.join(' | '))
10
+ end
11
+
12
+ def active_page(path)
13
+ "active" if current_page?(path)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,57 @@
1
+ module RocketJobMissionControl
2
+ module JobsHelper
3
+ STATE_ICON_MAP = {
4
+ queued: 'fa-bed warning',
5
+ paused: 'fa-pause warning',
6
+ running: 'fa-cog fa-spin primary',
7
+ completed: 'fa-check success',
8
+ aborted: 'fa-times warning',
9
+ }
10
+
11
+ STATE_CLASS_MAP = {
12
+ queued: 'warning',
13
+ paused: 'warning',
14
+ running: 'primary',
15
+ completed: 'success',
16
+ aborted: 'danger',
17
+ failed: 'danger',
18
+ }
19
+
20
+ def job_state_icon(state)
21
+ STATE_ICON_MAP[state.to_sym] || 'fa-times danger'
22
+ end
23
+
24
+ def job_class(job)
25
+ STATE_CLASS_MAP[job.state.to_sym] || ""
26
+ end
27
+
28
+ def pretty_print_array_or_hash(arguments)
29
+ return arguments unless arguments.kind_of?(Array) || arguments.kind_of?(Hash)
30
+ json_string_options = {space: ' ', indent: ' ', array_nl: '<br />', object_nl: '<br />'}
31
+ JSON.generate(arguments, json_string_options).html_safe
32
+ end
33
+
34
+ def job_card_class(job)
35
+ map = {
36
+ running: 'callout-info',
37
+ completed: 'callout-success',
38
+ failed: 'callout-alert',
39
+ aborted: 'callout-warning',
40
+ }
41
+ "card callout " << map[job.state.to_sym].to_s
42
+ end
43
+
44
+ def job_selected_class(job, selected_job = nil)
45
+ if selected_job.present? && job.id == selected_job.id
46
+ ' text-info'
47
+ else
48
+ ' text-muted'
49
+ end
50
+ end
51
+
52
+ def job_title(job)
53
+ perform_method = job.perform_method == :perform ? '' : "##{job.perform_method}"
54
+ "#{job.class.name}#{perform_method}"
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,14 @@
1
+ module RocketJobMissionControl
2
+ module WorkersHelper
3
+
4
+ def worker_card_class(worker)
5
+ map = {
6
+ running: 'callout-success-top',
7
+ paused: 'callout-warning-top',
8
+ stopping: 'callout-alert-top',
9
+ }
10
+ map[worker.state] || 'callout-info-top'
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,43 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title= title
5
+
6
+ %link{rel: "icon", type: "image/png", href: "/assets/favicon.png"}
7
+ %link{rel: "apple-touch-icon-precomposed", href: "/assets/apple-touch-icon.png"}
8
+
9
+ %meta{'http-equiv' => "Content-Type", content: "text/html; charset=UTF-8"}
10
+ %meta{'http-equiv' => "Content-Script-Type", content: "text/javascript"}
11
+ %meta{'http-equiv' =>"X-UA-Compatible", content: "IE=edge" }
12
+ %meta{name: "viewport", content: "width=device-width, initial-scale=1"}
13
+ = yield :meta
14
+
15
+
16
+ = stylesheet_link_tag "rocket_job_mission_control/application", :media => "all"
17
+ = javascript_include_tag "rocket_job_mission_control/application"
18
+
19
+ = csrf_meta_tag
20
+
21
+ %link{href: "//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css", rel: "stylesheet"}/
22
+
23
+ %body.rocket_job
24
+ #wrapper.toggled
25
+ = render partial: 'layouts/rocket_job_mission_control/partials/sidebar'
26
+
27
+ #page-content-wrapper
28
+ = render partial: 'layouts/rocket_job_mission_control/partials/header'
29
+
30
+ .flash
31
+ - flash.each do |key, msg|
32
+ - if msg
33
+ .alert{class: "alert-#{key} alert-dismissable", role: 'alert'}
34
+ %button.close{ data: { dismiss: 'alert' } }
35
+ %span &times;
36
+ -if msg.kind_of? Array
37
+ %ul.list-unstyled.margin-bottom-0
38
+ - msg.each do |m|
39
+ %li= m.html_safe
40
+ - else
41
+ = msg.html_safe
42
+
43
+ = yield