rocketjob_mission_control 3.1.0 → 3.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 +4 -4
- data/Rakefile +3 -1
- data/app/controllers/rocket_job_mission_control/active_workers_controller.rb +1 -0
- data/app/controllers/rocket_job_mission_control/application_controller.rb +15 -2
- data/app/controllers/rocket_job_mission_control/dirmon_entries_controller.rb +19 -2
- data/app/controllers/rocket_job_mission_control/jobs_controller.rb +45 -17
- data/app/controllers/rocket_job_mission_control/servers_controller.rb +18 -2
- data/app/datatables/rocket_job_mission_control/abstract_datatable.rb +0 -1
- data/app/datatables/rocket_job_mission_control/jobs_datatable.rb +8 -6
- data/app/datatables/rocket_job_mission_control/servers_datatable.rb +20 -8
- data/app/models/rocket_job_mission_control/access_policy.rb +50 -0
- data/app/models/rocket_job_mission_control/authorization.rb +22 -0
- data/app/views/rocket_job_mission_control/dirmon_entries/_sidebar.html.erb +5 -2
- data/app/views/rocket_job_mission_control/dirmon_entries/show.html.erb +8 -2
- data/app/views/rocket_job_mission_control/jobs/show.html.erb +9 -5
- data/app/views/rocket_job_mission_control/servers/index.html.erb +10 -8
- data/lib/rocket_job_mission_control/engine.rb +9 -0
- data/lib/rocket_job_mission_control/version.rb +1 -1
- data/test/controllers/rocket_job_mission_control/dirmon_entries_controller_test.rb +78 -1
- data/test/controllers/rocket_job_mission_control/jobs_controller_test.rb +52 -1
- data/test/controllers/rocket_job_mission_control/servers_controller_test.rb +58 -1
- data/test/test_helper.rb +12 -10
- data/vendor/assets/stylesheets/{fontawesome-all.min.css → fontawesome-all.min.css.erb} +1 -1
- metadata +20 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04c47815b195983663c44887317137d965b99c5a9e30d40f3b8969585dc7465a
|
4
|
+
data.tar.gz: 789ee3b6b5d9e006f8fa20d310fed0c30ed23dc89353a507cb7a544cfdaf46e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39413801aeb5be085f2f6ef7f7b9e44641efa786322126f34b9d05e5299ea149e92f5d6ef2d988521717d035d1a76bb300c5479ebf59a58441bb67212efd2621
|
7
|
+
data.tar.gz: 3f9e7b8308596809f4eeb73ed67da1f2fc0e65d879d7199f6f9d506acc2e33bfd7277a24cff3fb9b3a0706c940cfa7a0222acf4a22ecc13f8690c5ea3dea3672
|
data/Rakefile
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
require 'rubygems'
|
3
3
|
require 'bundler/setup'
|
4
4
|
|
5
|
-
|
5
|
+
require 'rails/version'
|
6
|
+
rakefile = Rails.version.to_f >= 5.2 ? '../rjmc/Rakefile' : '../rjmc4/Rakefile'
|
7
|
+
APP_RAKEFILE = File.expand_path(rakefile, __FILE__)
|
6
8
|
load 'rails/tasks/engine.rake'
|
7
9
|
|
8
10
|
require 'rake/testtask'
|
@@ -6,10 +6,23 @@ module RocketJobMissionControl
|
|
6
6
|
|
7
7
|
private
|
8
8
|
|
9
|
-
def with_time_zone
|
9
|
+
def with_time_zone(&block)
|
10
10
|
if time_zone = session['time_zone'] || 'UTC'
|
11
|
-
Time.use_zone(time_zone)
|
11
|
+
Time.use_zone(time_zone, &block)
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
15
|
+
def current_policy
|
16
|
+
@current_policy ||= begin
|
17
|
+
args =
|
18
|
+
if Config.authorization_callback
|
19
|
+
instance_exec(&Config.authorization_callback)
|
20
|
+
else
|
21
|
+
{roles: %i[admin]}
|
22
|
+
end
|
23
|
+
AccessPolicy.new(Authorization.new(args))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
14
27
|
end
|
15
28
|
end
|
@@ -1,13 +1,20 @@
|
|
1
1
|
module RocketJobMissionControl
|
2
2
|
class DirmonEntriesController < RocketJobMissionControl::ApplicationController
|
3
3
|
if Rails.version.to_i < 5
|
4
|
-
before_filter :find_entry_or_redirect, except: [
|
4
|
+
before_filter :find_entry_or_redirect, except: %i[index disabled enabled failed pending new create]
|
5
|
+
before_filter :authorize_read, only: %i[index disabled enabled failed pending]
|
5
6
|
before_filter :show_sidebar
|
6
7
|
else
|
7
|
-
before_action :find_entry_or_redirect, except: [
|
8
|
+
before_action :find_entry_or_redirect, except: %i[index disabled enabled failed pending new create]
|
9
|
+
before_action :authorize_read, only: %i[index disabled enabled failed pending]
|
8
10
|
before_action :show_sidebar
|
9
11
|
end
|
10
12
|
|
13
|
+
rescue_from AccessGranted::AccessDenied do |exception|
|
14
|
+
raise exception if Rails.env.development? || Rails.env.test?
|
15
|
+
redirect_to :back, alert: 'Access not authorized.'
|
16
|
+
end
|
17
|
+
|
11
18
|
def index
|
12
19
|
@data_table_url = dirmon_entries_url(format: 'json')
|
13
20
|
render_datatable(RocketJob::DirmonEntry.all, 'All')
|
@@ -46,6 +53,7 @@ module RocketJobMissionControl
|
|
46
53
|
end
|
47
54
|
|
48
55
|
def create
|
56
|
+
authorize! :create, RocketJob::DirmonEntry
|
49
57
|
@dirmon_entry = RocketJob::DirmonEntry.new(dirmon_params)
|
50
58
|
if properties = params[:rocket_job_dirmon_entry][:properties]
|
51
59
|
@dirmon_entry.properties = JobSanitizer.sanitize(properties, @dirmon_entry.job_class, @dirmon_entry, false)
|
@@ -59,14 +67,17 @@ module RocketJobMissionControl
|
|
59
67
|
end
|
60
68
|
|
61
69
|
def destroy
|
70
|
+
authorize! :destroy, @dirmon_entry
|
62
71
|
@dirmon_entry.destroy
|
63
72
|
redirect_to(dirmon_entries_path)
|
64
73
|
end
|
65
74
|
|
66
75
|
def edit
|
76
|
+
authorize! :edit, @dirmon_entry
|
67
77
|
end
|
68
78
|
|
69
79
|
def update
|
80
|
+
authorize! :update, @dirmon_entry
|
70
81
|
if properties = params[:rocket_job_dirmon_entry][:properties]
|
71
82
|
@dirmon_entry.properties = JobSanitizer.sanitize(properties, @dirmon_entry.job_class, @dirmon_entry, false)
|
72
83
|
end
|
@@ -78,6 +89,7 @@ module RocketJobMissionControl
|
|
78
89
|
end
|
79
90
|
|
80
91
|
def enable
|
92
|
+
authorize! :enable, @dirmon_entry
|
81
93
|
if @dirmon_entry.may_enable?
|
82
94
|
@dirmon_entry.enable!
|
83
95
|
redirect_to(rocket_job_mission_control.dirmon_entry_path(@dirmon_entry))
|
@@ -88,6 +100,7 @@ module RocketJobMissionControl
|
|
88
100
|
end
|
89
101
|
|
90
102
|
def disable
|
103
|
+
authorize! :disable, @dirmon_entry
|
91
104
|
if @dirmon_entry.may_disable?
|
92
105
|
@dirmon_entry.disable!
|
93
106
|
redirect_to(rocket_job_mission_control.dirmon_entry_path(@dirmon_entry))
|
@@ -104,6 +117,10 @@ module RocketJobMissionControl
|
|
104
117
|
|
105
118
|
private
|
106
119
|
|
120
|
+
def authorize_read
|
121
|
+
authorize! :read, RocketJob::DirmonEntry
|
122
|
+
end
|
123
|
+
|
107
124
|
def show_sidebar
|
108
125
|
@dirmon_sidebar = true
|
109
126
|
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
module RocketJobMissionControl
|
2
2
|
class JobsController < RocketJobMissionControl::ApplicationController
|
3
3
|
if Rails.version.to_i < 5
|
4
|
-
before_filter :find_job_or_redirect, except: [
|
4
|
+
before_filter :find_job_or_redirect, except: %i[index aborted completed failed paused queued running scheduled]
|
5
|
+
before_filter :authorize_read, only: %i[index running paused completed aborted failed queued scheduled]
|
5
6
|
before_filter :show_sidebar
|
6
7
|
else
|
7
|
-
before_action :find_job_or_redirect, except: [
|
8
|
+
before_action :find_job_or_redirect, except: %i[index aborted completed failed paused queued running scheduled]
|
9
|
+
before_action :authorize_read, only: %i[index running paused completed aborted failed queued scheduled]
|
8
10
|
before_action :show_sidebar
|
9
11
|
end
|
12
|
+
|
10
13
|
rescue_from StandardError, with: :error_occurred
|
11
14
|
|
12
15
|
def index
|
@@ -17,10 +20,14 @@ module RocketJobMissionControl
|
|
17
20
|
end
|
18
21
|
|
19
22
|
def running
|
20
|
-
jobs
|
23
|
+
# Prevent throttled jobs from displaying.
|
24
|
+
jobs = RocketJob::Job.
|
25
|
+
running.
|
26
|
+
where(:started_at.lte => (Time.now - 0.1)).
|
27
|
+
only(JobsDatatable::RUNNING_FIELDS)
|
21
28
|
@data_table_url = running_jobs_url(format: 'json')
|
22
29
|
|
23
|
-
render_datatable(jobs, 'Running', JobsDatatable::RUNNING_COLUMNS,
|
30
|
+
render_datatable(jobs, 'Running', JobsDatatable::RUNNING_COLUMNS, priority: :asc, created_at: :asc)
|
24
31
|
end
|
25
32
|
|
26
33
|
def paused
|
@@ -55,7 +62,7 @@ module RocketJobMissionControl
|
|
55
62
|
jobs = RocketJob::Job.queued_now.only(JobsDatatable::QUEUED_FIELDS)
|
56
63
|
@data_table_url = queued_jobs_url(format: 'json')
|
57
64
|
|
58
|
-
render_datatable(jobs, 'Queued', JobsDatatable::QUEUED_COLUMNS,
|
65
|
+
render_datatable(jobs, 'Queued', JobsDatatable::QUEUED_COLUMNS, priority: :asc, created_at: :asc)
|
59
66
|
end
|
60
67
|
|
61
68
|
def scheduled
|
@@ -66,6 +73,7 @@ module RocketJobMissionControl
|
|
66
73
|
end
|
67
74
|
|
68
75
|
def update
|
76
|
+
authorize! :update, @job
|
69
77
|
permitted_params = JobSanitizer.sanitize(params[:job], @job.class, @job)
|
70
78
|
if @job.errors.empty? && @job.valid? && @job.update_attributes(permitted_params)
|
71
79
|
redirect_to job_path(@job)
|
@@ -75,64 +83,75 @@ module RocketJobMissionControl
|
|
75
83
|
end
|
76
84
|
|
77
85
|
def abort
|
86
|
+
authorize! :abort, @job
|
78
87
|
@job.abort!
|
79
88
|
redirect_to(job_path(@job))
|
80
89
|
end
|
81
90
|
|
82
91
|
def destroy
|
92
|
+
authorize! :destroy, @job
|
83
93
|
@job.destroy
|
84
94
|
redirect_to(jobs_path)
|
85
95
|
end
|
86
96
|
|
87
97
|
def retry
|
98
|
+
authorize! :retry, @job
|
88
99
|
@job.retry!
|
89
100
|
redirect_to(job_path(@job))
|
90
101
|
end
|
91
102
|
|
92
103
|
def pause
|
104
|
+
authorize! :pause, @job
|
93
105
|
@job.pause!
|
94
106
|
redirect_to(job_path(@job))
|
95
107
|
end
|
96
108
|
|
97
109
|
def resume
|
110
|
+
authorize! :resume, @job
|
98
111
|
@job.resume!
|
99
112
|
redirect_to(job_path(@job))
|
100
113
|
end
|
101
114
|
|
102
115
|
def run_now
|
116
|
+
authorize! :run_now, @job
|
103
117
|
@job.unset(:run_at) if @job.scheduled?
|
104
118
|
redirect_to(job_path(@job))
|
105
119
|
end
|
106
120
|
|
107
121
|
def fail
|
122
|
+
authorize! :fail, @job
|
108
123
|
@job.fail!
|
109
124
|
|
110
125
|
redirect_to(job_path(@job))
|
111
126
|
end
|
112
127
|
|
113
128
|
def show
|
129
|
+
authorize! :read, @job
|
114
130
|
end
|
115
131
|
|
116
132
|
def edit
|
133
|
+
authorize! :edit, @job
|
117
134
|
end
|
118
135
|
|
119
136
|
def exceptions
|
137
|
+
authorize! :read, @job
|
120
138
|
@exceptions = @job.input.group_exceptions
|
121
139
|
end
|
122
140
|
|
123
141
|
def exception
|
142
|
+
authorize! :read, @job
|
124
143
|
error_type = params[:error_type]
|
125
144
|
offset = params.fetch(:offset, 0).to_i
|
126
145
|
|
127
146
|
unless error_type.present?
|
128
|
-
flash[:notice] = t(:no_errors, scope: [
|
147
|
+
flash[:notice] = t(:no_errors, scope: %i[job failures])
|
129
148
|
redirect_to(job_path(@job))
|
130
149
|
end
|
131
150
|
|
132
151
|
scope = @job.input.failed.where('exception.class_name' => error_type)
|
133
152
|
count = scope.count
|
134
153
|
unless count > 0
|
135
|
-
flash[:notice] = t(:no_errors, scope: [
|
154
|
+
flash[:notice] = t(:no_errors, scope: %i[job failures])
|
136
155
|
redirect_to(job_path(@job))
|
137
156
|
end
|
138
157
|
|
@@ -141,19 +160,23 @@ module RocketJobMissionControl
|
|
141
160
|
|
142
161
|
@pagination = {
|
143
162
|
offset: offset,
|
144
|
-
total: (count - 1)
|
163
|
+
total: (count - 1)
|
145
164
|
}
|
146
165
|
end
|
147
166
|
|
148
167
|
private
|
149
168
|
|
169
|
+
def authorize_read
|
170
|
+
authorize! :read, RocketJob::Job
|
171
|
+
end
|
172
|
+
|
150
173
|
def show_sidebar
|
151
174
|
@jobs_sidebar = true
|
152
175
|
end
|
153
176
|
|
154
177
|
def find_job_or_redirect
|
155
178
|
unless @job = RocketJob::Job.where(id: params[:id]).first
|
156
|
-
flash[:alert] = t(:failure, scope: [
|
179
|
+
flash[:alert] = t(:failure, scope: %i[job find], id: params[:id])
|
157
180
|
|
158
181
|
redirect_to(jobs_path)
|
159
182
|
end
|
@@ -169,8 +192,14 @@ module RocketJobMissionControl
|
|
169
192
|
else
|
170
193
|
logger.error "Error loading a job. #{exception.class}: #{exception.message}\n#{(exception.backtrace || []).join("\n")}"
|
171
194
|
end
|
172
|
-
|
173
|
-
|
195
|
+
|
196
|
+
flash[:danger] = if exception.is_a?(AccessGranted::AccessDenied)
|
197
|
+
'Access not authorized.'
|
198
|
+
else
|
199
|
+
'Error loading jobs.'
|
200
|
+
end
|
201
|
+
|
202
|
+
raise exception if Rails.env.development? || Rails.env.test?
|
174
203
|
redirect_to :back
|
175
204
|
end
|
176
205
|
|
@@ -184,7 +213,7 @@ module RocketJobMissionControl
|
|
184
213
|
end
|
185
214
|
format.json do
|
186
215
|
query = RocketJobMissionControl::Query.new(jobs, sort_order)
|
187
|
-
query.search_columns = [
|
216
|
+
query.search_columns = %i[_type description]
|
188
217
|
query.display_columns = columns.collect { |c| c[:field] }.compact
|
189
218
|
render(json: JobsDatatable.new(view_context, query, columns))
|
190
219
|
end
|
@@ -194,13 +223,12 @@ module RocketJobMissionControl
|
|
194
223
|
def build_table_layout(columns)
|
195
224
|
index = 0
|
196
225
|
columns.collect do |column|
|
197
|
-
h = {data: index.to_s}
|
198
|
-
h[:width] = column[:width] if column.
|
199
|
-
h[:orderable] = column[:orderable] if column.
|
200
|
-
index
|
226
|
+
h = { data: index.to_s }
|
227
|
+
h[:width] = column[:width] if column.key?(:width)
|
228
|
+
h[:orderable] = column[:orderable] if column.key?(:orderable)
|
229
|
+
index += 1
|
201
230
|
h
|
202
231
|
end
|
203
232
|
end
|
204
|
-
|
205
233
|
end
|
206
234
|
end
|
@@ -1,13 +1,20 @@
|
|
1
1
|
module RocketJobMissionControl
|
2
2
|
class ServersController < RocketJobMissionControl::ApplicationController
|
3
3
|
if Rails.version.to_i < 5
|
4
|
-
before_filter :find_server_or_redirect, only: [
|
4
|
+
before_filter :find_server_or_redirect, only: %i[stop pause resume destroy]
|
5
|
+
before_filter :authorize_read, only: %i[index starting running paused stopping zombie]
|
5
6
|
before_filter :show_sidebar
|
6
7
|
else
|
7
|
-
before_action :find_server_or_redirect, only: [
|
8
|
+
before_action :find_server_or_redirect, only: %i[stop pause resume destroy]
|
9
|
+
before_action :authorize_read, only: %i[index starting running paused stopping zombie]
|
8
10
|
before_action :show_sidebar
|
9
11
|
end
|
10
12
|
|
13
|
+
rescue_from AccessGranted::AccessDenied do |exception|
|
14
|
+
raise exception if Rails.env.development? || Rails.env.test?
|
15
|
+
redirect_to :back, alert: 'Access not authorized.'
|
16
|
+
end
|
17
|
+
|
11
18
|
def index
|
12
19
|
@data_table_url = servers_url(format: 'json')
|
13
20
|
@actions = [:pause_all, :resume_all, :stop_all, :destroy_zombies]
|
@@ -47,6 +54,7 @@ module RocketJobMissionControl
|
|
47
54
|
VALID_ACTIONS = [:stop_all, :pause_all, :resume_all, :destroy_zombies]
|
48
55
|
|
49
56
|
def update_all
|
57
|
+
authorize! :destroy, RocketJob::Server
|
50
58
|
server_action = params[:server_action].to_sym
|
51
59
|
if VALID_ACTIONS.include?(server_action)
|
52
60
|
RocketJob::Server.public_send(server_action.to_sym)
|
@@ -61,6 +69,7 @@ module RocketJobMissionControl
|
|
61
69
|
end
|
62
70
|
|
63
71
|
def stop
|
72
|
+
authorize! :stop, @server
|
64
73
|
if @server.may_stop?
|
65
74
|
@server.stop!
|
66
75
|
else
|
@@ -73,6 +82,7 @@ module RocketJobMissionControl
|
|
73
82
|
end
|
74
83
|
|
75
84
|
def destroy
|
85
|
+
authorize! :destroy, @server
|
76
86
|
@server.destroy
|
77
87
|
flash[:notice] = t(:success, scope: [:server, :destroy])
|
78
88
|
|
@@ -82,6 +92,7 @@ module RocketJobMissionControl
|
|
82
92
|
end
|
83
93
|
|
84
94
|
def pause
|
95
|
+
authorize! :pause, @server
|
85
96
|
if @server.may_pause?
|
86
97
|
@server.pause!
|
87
98
|
else
|
@@ -94,6 +105,7 @@ module RocketJobMissionControl
|
|
94
105
|
end
|
95
106
|
|
96
107
|
def resume
|
108
|
+
authorize! :resume, @server
|
97
109
|
if @server.may_resume?
|
98
110
|
@server.resume!
|
99
111
|
else
|
@@ -107,6 +119,10 @@ module RocketJobMissionControl
|
|
107
119
|
|
108
120
|
private
|
109
121
|
|
122
|
+
def authorize_read
|
123
|
+
authorize! :read, RocketJob::Server
|
124
|
+
end
|
125
|
+
|
110
126
|
def render_datatable(servers, description)
|
111
127
|
respond_to do |format|
|
112
128
|
format.html do
|
@@ -4,7 +4,7 @@ module RocketJobMissionControl
|
|
4
4
|
:abort_job_path, :job_path, :fail_job_path, :run_now_job_path, :pause_job_path,
|
5
5
|
:resume_job_path, :retry_job_path, :exception_job_path, :job_action_link, :exceptions_job_path, to: :@view
|
6
6
|
|
7
|
-
COMMON_FIELDS = [:id, :_type, :description, :completed_at, :created_at, :started_at, :state, :worker_name].freeze
|
7
|
+
COMMON_FIELDS = [:id, :_type, :description, :completed_at, :created_at, :started_at, :state, :worker_name, :login].freeze
|
8
8
|
|
9
9
|
ABORTED_COLUMNS = [
|
10
10
|
{display: 'Class', value: :class_with_link, field: '_type', width: '30%'},
|
@@ -156,19 +156,21 @@ module RocketJobMissionControl
|
|
156
156
|
def action_buttons(job)
|
157
157
|
events = valid_events(job)
|
158
158
|
buttons = "<div class='inline-job-actions'>"
|
159
|
-
if job.scheduled?
|
159
|
+
if job.scheduled? && view.can?(:run_now, job)
|
160
160
|
buttons += "#{ job_action_link('Run', run_now_job_path(job), :patch) }"
|
161
161
|
end
|
162
|
-
if events.include?(:pause)
|
162
|
+
if events.include?(:pause) && view.can?(:pause, job)
|
163
163
|
buttons += "#{ job_action_link('Pause', pause_job_path(job), :patch) }"
|
164
164
|
end
|
165
|
-
if events.include?(:resume)
|
165
|
+
if events.include?(:resume) && view.can?(:resume, job)
|
166
166
|
buttons += "#{ job_action_link('Resume', resume_job_path(job), :patch) }"
|
167
167
|
end
|
168
|
-
if events.include?(:retry)
|
168
|
+
if events.include?(:retry) && view.can?(:retry, job)
|
169
169
|
buttons += "#{ job_action_link('Retry', retry_job_path(job), :patch) }"
|
170
170
|
end
|
171
|
-
|
171
|
+
if view.can?(:destroy, job)
|
172
|
+
buttons += "#{ job_action_link('Destroy', job_path(job), :delete) }"
|
173
|
+
end
|
172
174
|
buttons += "</div>"
|
173
175
|
end
|
174
176
|
|