naf 2.1.6 → 2.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +0 -1
- data/README.rdoc +3 -3
- data/RELEASE_NOTES.rdoc +19 -0
- data/app/controllers/naf/api_simple_cluster_authenticator_application_controller.rb +9 -0
- data/app/controllers/naf/application_controller.rb +18 -1
- data/app/controllers/naf/log_parsers_controller.rb +11 -7
- data/app/models/logical/naf/construction_zone/boss.rb +21 -13
- data/app/models/logical/naf/construction_zone/foreman.rb +1 -1
- data/app/models/logical/naf/construction_zone/proletariat.rb +9 -1
- data/app/models/logical/naf/user_session.rb +53 -0
- data/app/models/naf/application_schedule.rb +14 -3
- data/app/models/naf/application_type.rb +7 -1
- data/app/models/naf/machine.rb +4 -4
- data/app/models/process/naf/log_archiver.rb +2 -1
- data/app/models/process/naf/log_archiver_queuer.rb +25 -0
- data/app/models/process/naf/logger/base.rb +0 -2
- data/app/views/naf/log_viewer/_log_display.html.erb +6 -1
- data/lib/naf.rb +16 -4
- data/lib/naf/configuration.rb +9 -3
- data/lib/naf/version.rb +1 -1
- data/naf.gemspec +2 -2
- data/spec/controllers/naf/application_controller_spec.rb +1 -1
- data/spec/factories/naf.rb +39 -0
- data/spec/models/logical/naf/construction_zone/boss_rspec.rb +119 -0
- data/spec/models/logical/naf/construction_zone/foreman_spec.rb +105 -0
- data/spec/models/logical/naf/construction_zone/proletariat_spec.rb +67 -0
- data/spec/models/logical/naf/construction_zone/work_order_spec.rb +2 -1
- data/spec/models/logical/naf/user_session_spec.rb +92 -0
- data/spec/models/naf/application_schedule_spec.rb +61 -0
- data/spec/models/naf/machine_spec.rb +5 -3
- metadata +13 -4
data/Gemfile
CHANGED
data/README.rdoc
CHANGED
@@ -40,8 +40,8 @@ Machines have an allocate-able number of slots of a specific affinity. Applicati
|
|
40
40
|
=== Tags
|
41
41
|
Scripts have tags to describe the stage/progress of the process. They can be system or custom tags. All tags are visible by the user, so set tags at different stages of your script. This is a way of knowing what is happening in the script without having to take a look at the logs.
|
42
42
|
|
43
|
-
|
44
43
|
=== Please find up-to-date information on Naf here: {Naf Wiki}[http://www.github.com/fiksu/naf/wiki]
|
45
|
-
=== Instructions on upgrading to Naf
|
44
|
+
=== Instructions on upgrading to Naf v2.1.8: {Instructions}[https://github.com/fiksu/naf/wiki/Upgrading-from-Naf-v2.1.6-to-Naf-v2.1.8]
|
45
|
+
=== Instructions on upgrading to Naf v2.1.6: {Instructions}[https://github.com/fiksu/naf/wiki/Upgrading-to-Naf-v2.1.6]
|
46
46
|
=== Instructions on upgrading to Naf v2.0: {Instructions}[https://github.com/fiksu/naf/wiki/Upgrading-to-Naf-v2.0]
|
47
|
-
=== Instructions on upgrading to Naf
|
47
|
+
=== Instructions on upgrading to Naf v1.1.4: {Instructions}[https://github.com/fiksu/naf/wiki/Upgrading-to-Naf-v1.1.4]
|
data/RELEASE_NOTES.rdoc
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
= Release Notes
|
2
2
|
|
3
|
+
=== Version 2.1.8
|
4
|
+
Bug fixes:
|
5
|
+
* Removed check for signed message. Encrypted data generated by ActiveSupport::MessageVerifier is different depending on the ruby version.
|
6
|
+
|
7
|
+
=== Version 2.1.7
|
8
|
+
Bug fixes:
|
9
|
+
* Boss#enqueue_command had the first two parameters switched
|
10
|
+
* Boss#enqueue_n_commands referenced a machine object, but that object did not exist in the scope
|
11
|
+
* Boss#enqueue_n_commands called job_affinity_tabs on a job when it should be calling historical_job_affinity_tabs
|
12
|
+
* Foreman#limited_by_run_group? checked the affinity_classification_name of an affinity, but did not check if the affinity was null
|
13
|
+
* Job exit status always set to 0, even after the job errors
|
14
|
+
* Unnecessary 'open4' require statements
|
15
|
+
* Deleted application still runs if it has an enabled schedule
|
16
|
+
* LogArchiver did not delete empty folders
|
17
|
+
|
18
|
+
Changes:
|
19
|
+
* Created a log archival queuer script
|
20
|
+
* Created Api Authenticator for logs
|
21
|
+
|
3
22
|
=== Version 2.1.6
|
4
23
|
Bug fixes:
|
5
24
|
* Historical jobs application_schedule_id was not getting set, causing the runner to constantly queue applications.
|
@@ -1,11 +1,13 @@
|
|
1
1
|
module Naf
|
2
|
-
class ApplicationController < Naf.
|
2
|
+
class ApplicationController < Naf.ui_controller_class
|
3
3
|
layout Naf.layout
|
4
4
|
|
5
5
|
require 'will_paginate/array'
|
6
6
|
|
7
7
|
protect_from_forgery
|
8
8
|
|
9
|
+
before_filter :check_naf_cookie_presence
|
10
|
+
|
9
11
|
protected
|
10
12
|
|
11
13
|
# Sets current rows_per_page direction from cookies or params.
|
@@ -39,5 +41,20 @@ module Naf
|
|
39
41
|
end
|
40
42
|
cookies[:search_status] = @search_status
|
41
43
|
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def check_naf_cookie_presence
|
48
|
+
user_session = ::Logical::Naf::UserSession.new(session[domain_cookie_name])
|
49
|
+
if !user_session.valid?
|
50
|
+
session.delete(domain_cookie_name)
|
51
|
+
session[domain_cookie_name] = user_session.token_cookie
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def domain_cookie_name
|
56
|
+
@domain_cookie_name ||= ::Naf.configuration.api_domain_cookie_name
|
57
|
+
end
|
58
|
+
|
42
59
|
end
|
43
60
|
end
|
@@ -1,15 +1,19 @@
|
|
1
1
|
module Naf
|
2
|
-
class LogParsersController < Naf::
|
2
|
+
class LogParsersController < Naf::ApiSimpleClusterAuthenticatorApplicationController
|
3
3
|
|
4
4
|
def logs
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
if naf_cookie_valid?
|
6
|
+
response = params['logical_type'].constantize.new(params).logs
|
7
|
+
if response.present?
|
8
|
+
success = true
|
9
|
+
else
|
10
|
+
success = false
|
11
|
+
end
|
12
|
+
|
13
|
+
render json: "convertToJsonCallback(" + { success: success }.merge(response).to_json + ")"
|
8
14
|
else
|
9
|
-
success
|
15
|
+
render json: "convertToJsonCallback(" + { success: false }.to_json + ")"
|
10
16
|
end
|
11
|
-
|
12
|
-
render json: "convertToJsonCallback(" + { success: success }.merge(response).to_json + ")"
|
13
17
|
end
|
14
18
|
|
15
19
|
end
|
@@ -60,8 +60,8 @@ module Logical::Naf::ConstructionZone
|
|
60
60
|
affinities = [],
|
61
61
|
prerequisites = [],
|
62
62
|
enqueue_backlogs = false)
|
63
|
-
work_order = WorkOrder.new(
|
64
|
-
|
63
|
+
work_order = WorkOrder.new(command,
|
64
|
+
application_type,
|
65
65
|
application_run_group_restriction,
|
66
66
|
application_run_group_name,
|
67
67
|
application_run_group_limit,
|
@@ -79,22 +79,18 @@ module Logical::Naf::ConstructionZone
|
|
79
79
|
|
80
80
|
def enqueue_n_commands_on_machines(parameters, number_of_jobs = :from_limit, machines = [])
|
81
81
|
logger.detail "enqueuing #{parameters[:command]} #{number_of_jobs} time(s) on #{machines.length} machine(s)"
|
82
|
+
# enqueue the command on each machine
|
82
83
|
machines.each do |machine|
|
83
84
|
number_of_jobs = (parameters[:application_run_group_quantum] || 1) if number_of_jobs == :from_limit
|
84
85
|
logger.info "enqueuing #{parameters[:command]} #{number_of_jobs} time(s) on #{machine}"
|
86
|
+
# enqueue the command number_of_jobs times
|
85
87
|
(1..number_of_jobs).each do
|
86
88
|
machine_parameters = {
|
87
89
|
application_run_group_restriction: ::Naf::ApplicationRunGroupRestriction.limited_per_machine
|
88
90
|
}.merge(parameters)
|
89
|
-
machine_parameters[:affinities] =
|
90
|
-
|
91
|
-
|
92
|
-
elsif machine_parameters[:affinities].is_a? Array
|
93
|
-
machine_parameters[:affinities]
|
94
|
-
else
|
95
|
-
[machine_parameters[:affinities]]
|
96
|
-
end
|
97
|
-
work_order = AdHocWorkOrder.new(machine_parameters)
|
91
|
+
machine_parameters[:affinities] = [machine.affinity] + affinities(machine_parameters)
|
92
|
+
work_order = AdHocWorkOrder.new(machine_parameters)
|
93
|
+
|
98
94
|
@foreman.enqueue(work_order)
|
99
95
|
end
|
100
96
|
end
|
@@ -102,7 +98,7 @@ module Logical::Naf::ConstructionZone
|
|
102
98
|
|
103
99
|
def enqueue_n_commands(parameters, number_of_jobs = :from_limit)
|
104
100
|
number_of_jobs = (parameters[:application_run_group_quantum] || 1) if number_of_jobs == :from_limit
|
105
|
-
logger.info "enqueuing #{parameters[:command]} #{number_of_jobs} time(s)
|
101
|
+
logger.info "enqueuing #{parameters[:command]} #{number_of_jobs} time(s)"
|
106
102
|
(1..number_of_jobs).each do
|
107
103
|
work_order = AdHocWorkOrder.new(parameters)
|
108
104
|
@foreman.enqueue(work_order)
|
@@ -115,7 +111,19 @@ module Logical::Naf::ConstructionZone
|
|
115
111
|
job.application_run_group_name,
|
116
112
|
job.application_run_group_limit,
|
117
113
|
job.priority,
|
118
|
-
job.
|
114
|
+
job.historical_job_affinity_tabs.map{|jat| jat.affinity})
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def affinities(params)
|
120
|
+
if params[:affinities].nil?
|
121
|
+
[]
|
122
|
+
elsif params[:affinities].is_a? Array
|
123
|
+
params[:affinities]
|
124
|
+
else
|
125
|
+
[params[:affinities]]
|
126
|
+
end
|
119
127
|
end
|
120
128
|
|
121
129
|
end
|
@@ -32,7 +32,7 @@ module Logical::Naf::ConstructionZone
|
|
32
32
|
machine_affinity = nil
|
33
33
|
affinities.each do |affinity|
|
34
34
|
machine_affinity = ::Naf::Affinity.find_by_id(affinity[:affinity_id])
|
35
|
-
if machine_affinity.affinity_classification_name == 'machine'
|
35
|
+
if machine_affinity.present? && machine_affinity.affinity_classification_name == 'machine'
|
36
36
|
break
|
37
37
|
end
|
38
38
|
end
|
@@ -3,7 +3,8 @@ module Logical::Naf::ConstructionZone
|
|
3
3
|
def create_job(parameters, affinities, prerequisites)
|
4
4
|
::Naf::HistoricalJob.transaction do
|
5
5
|
historical_job = create_historical_job(parameters, affinities, prerequisites)
|
6
|
-
|
6
|
+
create_queued_job(historical_job)
|
7
|
+
|
7
8
|
return historical_job
|
8
9
|
end
|
9
10
|
end
|
@@ -11,16 +12,20 @@ module Logical::Naf::ConstructionZone
|
|
11
12
|
def create_historical_job(parameters, affinities, prerequisites)
|
12
13
|
::Naf::HistoricalJob.transaction do
|
13
14
|
historical_job = ::Naf::HistoricalJob.create!(parameters)
|
15
|
+
# Create affinity tabs, if affinities are provided
|
14
16
|
affinities.each do |affinity|
|
15
17
|
::Naf::HistoricalJobAffinityTab.create(affinity.merge(historical_job_id: historical_job.id))
|
16
18
|
end
|
19
|
+
# Verify there is no loop found in prerequisites
|
17
20
|
historical_job.verify_prerequisites(prerequisites)
|
21
|
+
# Create historical job prerequesites, if prerequisites are provided
|
18
22
|
prerequisites.each do |prerequisite|
|
19
23
|
::Naf::HistoricalJobPrerequisite.create({
|
20
24
|
historical_job_id: historical_job.id,
|
21
25
|
prerequisite_historical_job_id: prerequisite.id
|
22
26
|
})
|
23
27
|
end
|
28
|
+
|
24
29
|
return historical_job
|
25
30
|
end
|
26
31
|
end
|
@@ -36,6 +41,9 @@ module Logical::Naf::ConstructionZone
|
|
36
41
|
priority: historical_job.priority)
|
37
42
|
queued_job.id = historical_job.id
|
38
43
|
queued_job.save!
|
44
|
+
|
45
|
+
return queued_job
|
39
46
|
end
|
47
|
+
|
40
48
|
end
|
41
49
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Logical
|
2
|
+
module Naf
|
3
|
+
class UserSession
|
4
|
+
|
5
|
+
attr_reader :message
|
6
|
+
|
7
|
+
def initialize(signed_message)
|
8
|
+
@message = self.class.unsign_message(signed_message)
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid?
|
12
|
+
message.present? && message[:value].present? &&
|
13
|
+
(Time.zone.now - message[:value]) < ::Naf.configuration.
|
14
|
+
simple_cluster_authenticator_cookie_expiration_time
|
15
|
+
end
|
16
|
+
|
17
|
+
def token_cookie
|
18
|
+
self.class.sign_message(self.class.build_token_cookie)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.build_token_cookie
|
22
|
+
{
|
23
|
+
value: Time.zone.now
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
# Sign the provided string using a MessageVerifier.
|
28
|
+
def self.sign_message(message)
|
29
|
+
self.message_verifier.generate(message) if !message.nil?
|
30
|
+
end
|
31
|
+
|
32
|
+
# Unsign the provided string using a MessageVerifier.
|
33
|
+
def self.unsign_message(message)
|
34
|
+
if message.nil?
|
35
|
+
return nil
|
36
|
+
end
|
37
|
+
|
38
|
+
begin
|
39
|
+
self.message_verifier.verify(message)
|
40
|
+
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns an ActiveSuport MessageVerifier for signing/unsigning strings seeded with the
|
46
|
+
# applications secret token.
|
47
|
+
def self.message_verifier
|
48
|
+
@@message_verifier ||= ActiveSupport::MessageVerifier.new(Rails.application.class.config.secret_token)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -106,7 +106,7 @@ module Naf
|
|
106
106
|
schedules = ::Naf::ApplicationSchedule.
|
107
107
|
joins(:run_interval_style).
|
108
108
|
where("#{Naf.schema_name}.run_interval_styles.name IN (?)", ['at beginning of day', 'at beginning of hour']).
|
109
|
-
enabled.select do |schedule|
|
109
|
+
enabled.application_not_deleted.select do |schedule|
|
110
110
|
|
111
111
|
interval_time = time.to_date
|
112
112
|
if schedule.run_interval_style.name == 'at beginning of day'
|
@@ -133,7 +133,7 @@ module Naf
|
|
133
133
|
schedules = ::Naf::ApplicationSchedule.
|
134
134
|
joins(:run_interval_style).
|
135
135
|
where("#{Naf.schema_name}.run_interval_styles.name = ?", 'after previous run').
|
136
|
-
enabled.select do |schedule|
|
136
|
+
enabled.application_not_deleted.select do |schedule|
|
137
137
|
|
138
138
|
(not_finished_applications[schedule.id].nil? &&
|
139
139
|
(application_last_runs[schedule.id].nil? ||
|
@@ -149,13 +149,24 @@ module Naf
|
|
149
149
|
::Naf::ApplicationSchedule.
|
150
150
|
joins(:run_interval_style).
|
151
151
|
where("#{Naf.schema_name}.run_interval_styles.name = ?", 'keep running').
|
152
|
-
enabled
|
152
|
+
enabled.application_not_deleted
|
153
153
|
end
|
154
154
|
|
155
155
|
def self.enabled
|
156
156
|
where(enabled: true)
|
157
157
|
end
|
158
158
|
|
159
|
+
def self.application_not_deleted
|
160
|
+
where("
|
161
|
+
NOT EXISTS (
|
162
|
+
SELECT 1
|
163
|
+
FROM #{Naf.schema_name}.applications AS app
|
164
|
+
WHERE app.id = #{Naf.schema_name}.application_schedules.application_id AND
|
165
|
+
app.deleted = true
|
166
|
+
)
|
167
|
+
")
|
168
|
+
end
|
169
|
+
|
159
170
|
def self.should_be_queued
|
160
171
|
current_time = Time.zone.now
|
161
172
|
# Applications that are still running
|
@@ -33,8 +33,14 @@ module Naf
|
|
33
33
|
self.send(invocation_method.to_sym, job)
|
34
34
|
end
|
35
35
|
|
36
|
+
# This method calls Process.spawn to excute a built command. The first part
|
37
|
+
# of the command is the execution of the job command, redirecting stderr to
|
38
|
+
# stdout. Stdout and stderr are then sent through a pipe to be used as input
|
39
|
+
# for the job logger. The job logger will also redirect stderr to stdout, and
|
40
|
+
# save any crash logs. At the end of the built command, there is a exit $PIPESTATUS
|
41
|
+
# command that will return the exit status of the whole command.
|
36
42
|
def invoke(job, job_command)
|
37
|
-
command = job_command + " 2>&1 | #{JOB_LOGGER} >> #{LOGGING_ROOT_DIRECTORY}/naf/crash.log 2>&1"
|
43
|
+
command = job_command + " 2>&1 | #{JOB_LOGGER} >> #{LOGGING_ROOT_DIRECTORY}/naf/crash.log 2>&1; exit $PIPESTATUS"
|
38
44
|
Process.spawn({ 'NAF_JOB_ID' => job.id.to_s }, command)
|
39
45
|
end
|
40
46
|
|
data/app/models/naf/machine.rb
CHANGED
@@ -202,9 +202,9 @@ module Naf
|
|
202
202
|
started_on(self).each do |job|
|
203
203
|
|
204
204
|
marking_at = Time.zone.now
|
205
|
-
machine_logger.alarm "#{by_machine.id} marking #{job} as dead at #{marking_at}"
|
205
|
+
machine_logger.alarm "#{by_machine.try(:id)} marking #{job} as dead at #{marking_at}"
|
206
206
|
job.request_to_terminate = job.historical_job.request_to_terminate = true
|
207
|
-
job.marked_dead_by_machine_id = job.historical_job.marked_dead_by_machine_id = by_machine.id
|
207
|
+
job.marked_dead_by_machine_id = job.historical_job.marked_dead_by_machine_id = by_machine.try(:id)
|
208
208
|
job.marked_dead_at = job.historical_job.marked_dead_at = marking_at
|
209
209
|
job.historical_job.finished_at = marking_at
|
210
210
|
job.save!
|
@@ -216,7 +216,7 @@ module Naf
|
|
216
216
|
marking_at = Time.zone.now
|
217
217
|
machine_logger.alarm "#{by_machine.try(:id)} marking #{self} as down at #{marking_at}"
|
218
218
|
self.marked_down = true
|
219
|
-
self.marked_down_by_machine_id = by_machine.id
|
219
|
+
self.marked_down_by_machine_id = by_machine.try(:id)
|
220
220
|
self.marked_down_at = marking_at
|
221
221
|
save!
|
222
222
|
mark_processes_as_dead(by_machine)
|
@@ -224,7 +224,7 @@ module Naf
|
|
224
224
|
|
225
225
|
def affinity
|
226
226
|
return ::Naf::Affinity.
|
227
|
-
where(affinity_classification_id: ::Naf::AffinityClassification.
|
227
|
+
where(affinity_classification_id: ::Naf::AffinityClassification.machine.id,
|
228
228
|
affinity_name: self.id.to_s).first
|
229
229
|
end
|
230
230
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Process::Naf
|
2
|
+
class LogArchiverQueuer < ::Process::Naf::Application
|
3
|
+
|
4
|
+
def work
|
5
|
+
# Archive logs
|
6
|
+
params = { command: log_archiver.command }
|
7
|
+
boss.enqueue_n_commands_on_machines(params, :from_limit, machines)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def boss
|
13
|
+
::Logical::Naf::ConstructionZone::Boss.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def machines
|
17
|
+
::Naf::Machine.enabled.up.all
|
18
|
+
end
|
19
|
+
|
20
|
+
def log_archiver
|
21
|
+
::Naf::Application.where(command: '::Process::Naf::LogArchiver.run').first
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -165,7 +165,12 @@
|
|
165
165
|
}
|
166
166
|
},
|
167
167
|
error: function(response) {
|
168
|
-
|
168
|
+
message = ' <span>Failed to retrieve ' + '<%= record_type %>' + '(' +
|
169
|
+
'<%= record_id %>' + ') logs from ' + '<%= logs_url %>'.match(/^https?\:\/\/([^\/?#]+)/).pop() + '. Please refer to ' +
|
170
|
+
'Naf FAQs on the' + ' wiki'.link('https://github.com/fiksu/naf/wiki/Frequently-Asked-Questions') +
|
171
|
+
' for further information.<br></span>';
|
172
|
+
|
173
|
+
jQuery('#stdout').prepend(message);
|
169
174
|
}
|
170
175
|
});
|
171
176
|
}
|
data/lib/naf.rb
CHANGED
@@ -21,10 +21,6 @@ module Naf
|
|
21
21
|
configuration.model_class.constantize
|
22
22
|
end
|
23
23
|
|
24
|
-
def controller_class
|
25
|
-
configuration.controller_class.constantize
|
26
|
-
end
|
27
|
-
|
28
24
|
def title
|
29
25
|
configuration.title
|
30
26
|
end
|
@@ -33,6 +29,22 @@ module Naf
|
|
33
29
|
configuration.layout
|
34
30
|
end
|
35
31
|
|
32
|
+
def ui_controller_class
|
33
|
+
configuration.ui_controller_class.constantize
|
34
|
+
end
|
35
|
+
|
36
|
+
def api_controller_class
|
37
|
+
configuration.api_controller_class.constantize
|
38
|
+
end
|
39
|
+
|
40
|
+
def api_domain_cookie_name
|
41
|
+
configuration.api_domain_cookie_name
|
42
|
+
end
|
43
|
+
|
44
|
+
def simple_cluster_authenticator_cookie_expiration_time
|
45
|
+
configuration.simple_cluster_authenticator_cookie_expiration_time
|
46
|
+
end
|
47
|
+
|
36
48
|
def using_another_database?
|
37
49
|
model_class != ActiveRecord::Base
|
38
50
|
end
|
data/lib/naf/configuration.rb
CHANGED
@@ -2,17 +2,23 @@ module Naf
|
|
2
2
|
class Configuration
|
3
3
|
attr_accessor :schema_name,
|
4
4
|
:model_class,
|
5
|
-
:
|
5
|
+
:ui_controller_class,
|
6
|
+
:api_controller_class,
|
6
7
|
:title,
|
7
8
|
:layout,
|
8
|
-
:default_page_options
|
9
|
+
:default_page_options,
|
10
|
+
:api_domain_cookie_name,
|
11
|
+
:simple_cluster_authenticator_cookie_expiration_time
|
9
12
|
|
10
13
|
def initialize
|
11
14
|
@model_class = "::ActiveRecord::Base"
|
12
|
-
@
|
15
|
+
@ui_controller_class = "::ApplicationController"
|
13
16
|
@title = "Naf - a Rails Job Scheduling Engine"
|
14
17
|
@layout = "naf_layout"
|
15
18
|
@default_page_options = [10, 20, 50, 100, 250, 500, 750, 1000, 1500, 2000]
|
19
|
+
@api_controller_class = "Naf::ApiSimpleClusterAuthenticatorApplicationController"
|
20
|
+
@simple_cluster_authenticator_cookie_expiration_time = 1.week
|
21
|
+
@api_domain_cookie_name = "naf_#{Rails.application.class.parent.name.underscore}"
|
16
22
|
end
|
17
23
|
|
18
24
|
end
|
data/lib/naf/version.rb
CHANGED
data/naf.gemspec
CHANGED
@@ -8,11 +8,11 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.name = "naf"
|
9
9
|
s.version = Naf::VERSION
|
10
10
|
s.license = 'New BSD License'
|
11
|
-
s.date = '2014-03-
|
11
|
+
s.date = '2014-03-24'
|
12
12
|
s.summary = "Creates infrastructure for a customizable and robust Postgres-backed script scheduling/running"
|
13
13
|
s.description = "A cloud based distributed cron, application framework and operations console. Naf works as a distributed script running " +
|
14
14
|
"system that provides scheduling, logging, alarming, machine redundancy, and the ability to set constraint during script execution"
|
15
|
-
s.authors = ["Keith Gabryelski", "Leonardo Meira"
|
15
|
+
s.authors = ["Keith Gabryelski", "Leonardo Meira"]
|
16
16
|
s.email = ['keith@fiksu.com', 'lmeira@fiksu.com']
|
17
17
|
s.files = `git ls-files`.split("\n")
|
18
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
module Naf
|
4
4
|
describe ApplicationController do
|
5
5
|
it "should inherit from specified controller" do
|
6
|
-
ApplicationController.superclass.should == Naf.
|
6
|
+
ApplicationController.superclass.should == Naf.ui_controller_class
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
data/spec/factories/naf.rb
CHANGED
@@ -224,6 +224,11 @@ FactoryGirl.define do
|
|
224
224
|
end
|
225
225
|
end
|
226
226
|
|
227
|
+
factory :run_group_restriction, class: ::Naf::ApplicationRunGroupRestriction do
|
228
|
+
id 4
|
229
|
+
application_run_group_restriction_name "restriction"
|
230
|
+
end
|
231
|
+
|
227
232
|
#############################################################
|
228
233
|
####### Application Types #################################
|
229
234
|
#############################################################
|
@@ -307,6 +312,16 @@ FactoryGirl.define do
|
|
307
312
|
end
|
308
313
|
end
|
309
314
|
|
315
|
+
factory :machine_affinity, class: ::Naf::Affinity do
|
316
|
+
id 4
|
317
|
+
association :affinity_classification, factory: :machine_affinity_classification
|
318
|
+
affinity_name "machine"
|
319
|
+
# Ensure single creation
|
320
|
+
initialize_with do
|
321
|
+
::Naf::Affinity.find_or_initialize_by_id(id)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
310
325
|
factory :affinity, class: ::Naf::Affinity do
|
311
326
|
association :affinity_classification, factory: :purpose_affinity_classification
|
312
327
|
sequence(:affinity_name) do |n|
|
@@ -342,6 +357,22 @@ FactoryGirl.define do
|
|
342
357
|
end
|
343
358
|
end
|
344
359
|
|
360
|
+
factory :weight_affinity_classification, class: ::Naf::AffinityClassification do
|
361
|
+
id 4
|
362
|
+
affinity_classification_name "weight"
|
363
|
+
initialize_with do
|
364
|
+
::Naf::AffinityClassification.find_or_initialize_by_id(id)
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
factory :machine_affinity_classification, class: ::Naf::AffinityClassification do
|
369
|
+
id 5
|
370
|
+
affinity_classification_name "machine"
|
371
|
+
initialize_with do
|
372
|
+
::Naf::AffinityClassification.find_or_initialize_by_id(id)
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
345
376
|
factory :affinity_classification, class: ::Naf::AffinityClassification do
|
346
377
|
sequence(:affinity_classification_name) { |n| "affinity_classification_#{n}" }
|
347
378
|
end
|
@@ -368,6 +399,14 @@ FactoryGirl.define do
|
|
368
399
|
association :affinity, factory: :canary_affinity
|
369
400
|
end
|
370
401
|
|
402
|
+
factory :weight_job_affinity_tab, parent: :job_affinity_tab_base do
|
403
|
+
association :affinity, factory: :weight_affinity
|
404
|
+
end
|
405
|
+
|
406
|
+
factory :machine_job_affinity_tab, parent: :job_affinity_tab_base do
|
407
|
+
association :affinity, factory: :machine_affinity
|
408
|
+
end
|
409
|
+
|
371
410
|
# Application Schedule Affinity Tabs
|
372
411
|
|
373
412
|
factory :app_schedule_affinity_tab_base, class: ::Naf::ApplicationScheduleAffinityTab do
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Logical::Naf::ConstructionZone
|
4
|
+
|
5
|
+
describe Boss do
|
6
|
+
let!(:boss) { Logical::Naf::ConstructionZone::Boss.new }
|
7
|
+
let!(:work_order) {
|
8
|
+
Logical::Naf::ConstructionZone::WorkOrder.new('::Process::Naf::Janitor.run')
|
9
|
+
}
|
10
|
+
let(:params) { {
|
11
|
+
command: '::Process::Naf::Janitor.run',
|
12
|
+
application_type: ::Naf::ApplicationType.rails,
|
13
|
+
application_run_group_restriction: ::Naf::ApplicationRunGroupRestriction.
|
14
|
+
limited_per_all_machines,
|
15
|
+
application_run_group_name: '::Process::Naf::Janitor.run',
|
16
|
+
application_run_group_limit: 1,
|
17
|
+
priority: 0,
|
18
|
+
affinities: [],
|
19
|
+
prerequisites: [],
|
20
|
+
enqueue_backlogs: false,
|
21
|
+
application: nil,
|
22
|
+
application_schedule: nil
|
23
|
+
} }
|
24
|
+
|
25
|
+
shared_examples 'create one historical job' do |num_records|
|
26
|
+
it 'return the correct object' do
|
27
|
+
job.should be_a(::Naf::HistoricalJob)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'return correct number of historical jobs' do
|
31
|
+
::Naf::HistoricalJob.should have(num_records).records
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#enqueue_application' do
|
36
|
+
let(:application) { FactoryGirl.create(:application) }
|
37
|
+
let!(:job) {
|
38
|
+
boss.enqueue_application(application,
|
39
|
+
::Naf::ApplicationRunGroupRestriction.no_limit,
|
40
|
+
application.command)
|
41
|
+
}
|
42
|
+
|
43
|
+
it_should_behave_like 'create one historical job', 1
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#enqueue_application_schedule' do
|
47
|
+
let!(:job) { boss.enqueue_application_schedule(FactoryGirl.create(:schedule)) }
|
48
|
+
|
49
|
+
it_should_behave_like 'create one historical job', 1
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#enqueue_rails_command' do
|
53
|
+
let!(:job) { boss.enqueue_rails_command('::Process::Naf::Janitor.run') }
|
54
|
+
|
55
|
+
it_should_behave_like 'create one historical job', 1
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#enqueue_command' do
|
59
|
+
let!(:job) { boss.enqueue_command('::Process::Naf::Janitor.run') }
|
60
|
+
|
61
|
+
it_should_behave_like 'create one historical job', 1
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#enqueue_ad_hoc_command' do
|
65
|
+
let!(:job) { boss.enqueue_ad_hoc_command(params) }
|
66
|
+
|
67
|
+
it_should_behave_like 'create one historical job', 1
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#enqueue_n_commands_on_machines' do
|
71
|
+
let!(:affinity) { FactoryGirl.create(:normal_affinity) }
|
72
|
+
|
73
|
+
before do
|
74
|
+
params[:application_run_group_quantum] = 2
|
75
|
+
params[:application_run_group_limit] = 5
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'not create a historical job when array of machines is empty' do
|
79
|
+
boss.enqueue_n_commands_on_machines({})
|
80
|
+
::Naf::HistoricalJob.should have(0).records
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'create two historical jobs when a machine is present' do
|
84
|
+
machine = FactoryGirl.create(:machine)
|
85
|
+
classification = FactoryGirl.create(:location_affinity_classification)
|
86
|
+
FactoryGirl.create(:affinity, id: 5,
|
87
|
+
affinity_name: machine.id.to_s,
|
88
|
+
affinity_classification: classification)
|
89
|
+
|
90
|
+
boss.enqueue_n_commands_on_machines(params, :from_limit, [machine])
|
91
|
+
::Naf::HistoricalJob.should have(2).records
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe '#enqueue_n_commands' do
|
96
|
+
subject { boss.enqueue_n_commands(params) }
|
97
|
+
|
98
|
+
it 'create one historical jobs when application_run_group_quantum is not specified' do
|
99
|
+
params[:application_run_group_quantum] = 1
|
100
|
+
subject
|
101
|
+
::Naf::HistoricalJob.should have(1).records
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'create five historical jobs' do
|
105
|
+
params[:application_run_group_quantum] = 5
|
106
|
+
params[:application_run_group_limit] = 5
|
107
|
+
subject
|
108
|
+
::Naf::HistoricalJob.should have(5).records
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe '#reenqueue' do
|
113
|
+
let!(:job) { boss.reenqueue(FactoryGirl.create(:job)) }
|
114
|
+
|
115
|
+
it_should_behave_like 'create one historical job', 2
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Logical::Naf::ConstructionZone
|
4
|
+
describe Foreman do
|
5
|
+
|
6
|
+
let!(:foreman) { Logical::Naf::ConstructionZone::Foreman.new }
|
7
|
+
let!(:work_order) {
|
8
|
+
Logical::Naf::ConstructionZone::WorkOrder.new('::Process::Naf::Janitor.run')
|
9
|
+
}
|
10
|
+
|
11
|
+
describe '#enqueue' do
|
12
|
+
it 'return historical job when enqueue_backlogs is set to true' do
|
13
|
+
work_order.enqueue_backlogs
|
14
|
+
foreman.enqueue(work_order).should be_a(::Naf::HistoricalJob)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'return historical job when enqueue_backlogs is set to false and there is not run group limit' do
|
18
|
+
foreman.enqueue(work_order).should be_a(::Naf::HistoricalJob)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'return nil when work order is limited by run group' do
|
22
|
+
foreman.should_receive(:limited_by_run_group?).and_return(true)
|
23
|
+
foreman.enqueue(work_order).should be_nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#limited_by_run_group?' do
|
28
|
+
let!(:no_limit) { FactoryGirl.create(:no_limit) }
|
29
|
+
let!(:limited_per_machine) { FactoryGirl.create(:limited_per_machine) }
|
30
|
+
let!(:limited_per_all_machines) { FactoryGirl.create(:limited_per_all_machines) }
|
31
|
+
|
32
|
+
it 'return false when run group restriction is set to no limit' do
|
33
|
+
foreman.limited_by_run_group?(no_limit, nil, nil, []).should be_false
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'return false when run group limit is nil' do
|
37
|
+
foreman.limited_by_run_group?(limited_per_machine, 'test', nil, []).should be_false
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'return false when run group name is nil' do
|
41
|
+
foreman.limited_by_run_group?(limited_per_machine, nil, 1, []).should be_false
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'run group restriction is set to limited per machine' do
|
45
|
+
let!(:machine) { FactoryGirl.create(:machine) }
|
46
|
+
let(:historical_job) { FactoryGirl.create(:job, application_run_group_name: 'test') }
|
47
|
+
let(:tab) { FactoryGirl.create(:machine_job_affinity_tab, historical_job_id: historical_job.id) }
|
48
|
+
|
49
|
+
before do
|
50
|
+
FactoryGirl.create(:queued_job, application_run_group_name: 'test', id: historical_job.id)
|
51
|
+
FactoryGirl.create(:running_job_base, application_run_group_name: 'test',
|
52
|
+
started_on_machine_id: machine.id,
|
53
|
+
application_run_group_name: 'test')
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'return false when application does not have affinity associated with machine' do
|
57
|
+
foreman.limited_by_run_group?(limited_per_machine, 'test', 1, []).should be_false
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'return false when limit is greater than number of running/queued jobs' do
|
61
|
+
foreman.limited_by_run_group?(
|
62
|
+
limited_per_machine, 'test', 5, [{ affinity_id: tab.affinity.id }]
|
63
|
+
).should be_false
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'return true when limit is equal to number of running/queued jobs' do
|
67
|
+
foreman.limited_by_run_group?(
|
68
|
+
limited_per_machine, 'test', 1, [{ affinity_id: tab.affinity.id }]
|
69
|
+
).should be_true
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'return true when limit is less than number of running/queued jobs' do
|
73
|
+
FactoryGirl.create(:running_job_base, application_run_group_name: 'test',
|
74
|
+
started_on_machine_id: machine.id,
|
75
|
+
application_run_group_name: 'test')
|
76
|
+
foreman.limited_by_run_group?(
|
77
|
+
limited_per_machine, 'test', 1, [{ affinity_id: tab.affinity.id }]
|
78
|
+
).should be_true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'run group restriction is set to limited per all machines' do
|
83
|
+
it 'return false when limit is greater than number of running/queued jobs' do
|
84
|
+
foreman.limited_by_run_group?(limited_per_all_machines, 'test', 1, []).should be_false
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'return true when limit is equal to number of running/queued jobs' do
|
88
|
+
FactoryGirl.create(:queued_job, application_run_group_name: 'test')
|
89
|
+
foreman.limited_by_run_group?(limited_per_all_machines, 'test', 1, []).should be_true
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'return true when limit is less than number of running/queued jobs' do
|
93
|
+
FactoryGirl.create(:queued_job, application_run_group_name: 'test')
|
94
|
+
FactoryGirl.create(:running_job_base, application_run_group_name: 'test')
|
95
|
+
foreman.limited_by_run_group?(limited_per_all_machines, 'test', 1, []).should be_true
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'return true when a different run group restriction is found' do
|
100
|
+
restriction = FactoryGirl.create(:run_group_restriction)
|
101
|
+
foreman.limited_by_run_group?(restriction, 'test', 1, []).should be_true
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Logical::Naf::ConstructionZone
|
4
|
+
|
5
|
+
describe Proletariat do
|
6
|
+
|
7
|
+
let!(:proletariat) { ::Logical::Naf::ConstructionZone::Proletariat.new }
|
8
|
+
let(:application) { FactoryGirl.create(:scheduled_application) }
|
9
|
+
let(:application_type) { FactoryGirl.create(:rails_app_type) }
|
10
|
+
let(:restriction) { FactoryGirl.create(:no_limit) }
|
11
|
+
let!(:params) {
|
12
|
+
{
|
13
|
+
command: '::Process::Naf::Janitor.run',
|
14
|
+
application_type_id: application_type.id,
|
15
|
+
application_run_group_restriction_id: restriction.id,
|
16
|
+
application_run_group_name: '::Process::Naf::Janitor.run',
|
17
|
+
application_run_group_limit: 1,
|
18
|
+
priority: 0,
|
19
|
+
application_id: application.id,
|
20
|
+
application_schedule_id: application.application_schedules.first.id
|
21
|
+
}
|
22
|
+
}
|
23
|
+
let!(:affinity) { { affinity_id: FactoryGirl.create(:normal_affinity).id } }
|
24
|
+
let!(:prerequisite) { FactoryGirl.create(:job) }
|
25
|
+
|
26
|
+
describe '#create_job' do
|
27
|
+
it 'return a historical job' do
|
28
|
+
proletariat.create_job(params, [], []).should be_a(::Naf::HistoricalJob)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#create_historical_job' do
|
33
|
+
let!(:historical_job) { proletariat.create_historical_job(params, [affinity], [prerequisite]) }
|
34
|
+
|
35
|
+
it 'return historical job when exception is not raised' do
|
36
|
+
historical_job.should be_a(::Naf::HistoricalJob)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'create a historical job affinity tab' do
|
40
|
+
::Naf::HistoricalJobAffinityTab.should have(1).records
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'create a historical job affinity tab' do
|
44
|
+
::Naf::HistoricalJobPrerequisite.should have(1).records
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'raise an exception when there is a loop found in prerequisites' do
|
48
|
+
prerequisite.should_receive(:prerequisites).and_raise(::Naf::HistoricalJob::JobPrerequisiteLoop.new(prerequisite))
|
49
|
+
begin
|
50
|
+
job = proletariat.create_historical_job(params, [affinity], [prerequisite])
|
51
|
+
rescue
|
52
|
+
end
|
53
|
+
job.should be_nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#create_queued_job' do
|
58
|
+
let!(:historical_job) { FactoryGirl.create(:scheduled_job) }
|
59
|
+
|
60
|
+
it 'return a queued job' do
|
61
|
+
historical_job.application_schedule_id = historical_job.application.application_schedules.first.id
|
62
|
+
proletariat.create_queued_job(historical_job).should be_a(::Naf::QueuedJob)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -21,6 +21,7 @@ module Logical::Naf::ConstructionZone
|
|
21
21
|
application_schedule_id: nil
|
22
22
|
}
|
23
23
|
}
|
24
|
+
|
24
25
|
it 'return correct values' do
|
25
26
|
work_order.historical_job_parameters.should == params
|
26
27
|
end
|
@@ -49,7 +50,7 @@ module Logical::Naf::ConstructionZone
|
|
49
50
|
|
50
51
|
it 'return hash with the affinity_id when a Machine object is provided' do
|
51
52
|
machine = FactoryGirl.create(:machine)
|
52
|
-
classification = FactoryGirl.create(:
|
53
|
+
classification = FactoryGirl.create(:machine_affinity_classification)
|
53
54
|
affinity = FactoryGirl.create(:affinity, id: 4,
|
54
55
|
affinity_name: machine.id.to_s,
|
55
56
|
affinity_classification: classification)
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Logical
|
4
|
+
module Naf
|
5
|
+
|
6
|
+
describe UserSession do
|
7
|
+
let!(:user_session) { ::Logical::Naf::UserSession.new(nil) }
|
8
|
+
|
9
|
+
describe '#valid?' do
|
10
|
+
it 'return false when message is not present' do
|
11
|
+
user_session.valid?.should be_false
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'return false when value is not present' do
|
15
|
+
user_session.instance_variable_set(:@message, {})
|
16
|
+
user_session.valid?.should be_false
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'return false when session is expired' do
|
20
|
+
user_session.instance_variable_set(:@message, { value: Time.zone.now - 1.month })
|
21
|
+
user_session.valid?.should be_false
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'return true for invalid signed message' do
|
25
|
+
user_session.instance_variable_set(:@message, { value: Time.zone.now - 1.hour })
|
26
|
+
user_session.valid?.should be_true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#token_cookie' do
|
31
|
+
let!(:signed_message) { user_session.token_cookie }
|
32
|
+
|
33
|
+
it 'not be nil' do
|
34
|
+
signed_message.should_not be_nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#build_token_cookie' do
|
39
|
+
before do
|
40
|
+
Timecop.freeze(Time.zone.now)
|
41
|
+
end
|
42
|
+
|
43
|
+
after do
|
44
|
+
Timecop.return
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'return hash with current time' do
|
48
|
+
::Logical::Naf::UserSession.build_token_cookie.should == { value: Time.zone.now }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#sign_message' do
|
53
|
+
it 'return nil when message is nil' do
|
54
|
+
::Logical::Naf::UserSession.sign_message(nil).should be_nil
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'sign the message when message is present' do
|
58
|
+
::Logical::Naf::UserSession.sign_message(::Logical::Naf::UserSession.build_token_cookie).
|
59
|
+
should =~ /^.{123}={1}-{2}[a-zA-Z0-9]{40}$/
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#unsign_message' do
|
64
|
+
it 'return nil when message is not signed' do
|
65
|
+
::Logical::Naf::UserSession.unsign_message(nil).should be_nil
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'return nil when InvalidSignature exception is raised' do
|
69
|
+
::Logical::Naf::UserSession.stub(:message_verifier).
|
70
|
+
and_raise(ActiveSupport::MessageVerifier::InvalidSignature)
|
71
|
+
::Logical::Naf::UserSession.unsign_message(nil).should be_nil
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'return message when signed message is valid' do
|
75
|
+
message_verifier = ActiveSupport::MessageVerifier.
|
76
|
+
new(Rails.application.class.config.secret_token)
|
77
|
+
message = { value: Time.zone.now }
|
78
|
+
|
79
|
+
::Logical::Naf::UserSession.
|
80
|
+
unsign_message(message_verifier.generate(message)).should == message
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#message_verifier' do
|
85
|
+
it 'return instance of ActiveSupport::MessageVerifier' do
|
86
|
+
::Logical::Naf::UserSession.message_verifier.should be_a(ActiveSupport::MessageVerifier)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
@@ -95,6 +95,12 @@ module Naf
|
|
95
95
|
time = Time.zone.now
|
96
96
|
::Naf::ApplicationSchedule.exact_schedules(time, {}, {}).should == []
|
97
97
|
end
|
98
|
+
|
99
|
+
it "return no schedules when application is deleted" do
|
100
|
+
schedule.application.deleted = true
|
101
|
+
schedule.application.save!
|
102
|
+
::Naf::ApplicationSchedule.exact_schedules(time, {}, {}).should == []
|
103
|
+
end
|
98
104
|
end
|
99
105
|
|
100
106
|
describe "#relative_schedules" do
|
@@ -116,6 +122,61 @@ module Naf
|
|
116
122
|
schedule.run_interval = 20
|
117
123
|
::Naf::ApplicationSchedule.relative_schedules(time, {}, apps).should == []
|
118
124
|
end
|
125
|
+
|
126
|
+
it "return no schedules when application is deleted" do
|
127
|
+
schedule.application.deleted = true
|
128
|
+
schedule.application.save!
|
129
|
+
::Naf::ApplicationSchedule.exact_schedules(time, {}, {}).should == []
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "#constant_schedules" do
|
134
|
+
it "return schedule when it is ready" do
|
135
|
+
schedule.run_interval_style.name = 'keep running'
|
136
|
+
schedule.run_interval_style.save!
|
137
|
+
|
138
|
+
::Naf::ApplicationSchedule.constant_schedules.should == [schedule]
|
139
|
+
end
|
140
|
+
|
141
|
+
it "return no schedules when application is deleted" do
|
142
|
+
schedule.application.deleted = true
|
143
|
+
schedule.application.save!
|
144
|
+
::Naf::ApplicationSchedule.constant_schedules.should == []
|
145
|
+
end
|
146
|
+
|
147
|
+
it "return no schedules when schedule is disabled" do
|
148
|
+
schedule.enabled = false
|
149
|
+
schedule.save!
|
150
|
+
::Naf::ApplicationSchedule.constant_schedules.should == []
|
151
|
+
end
|
152
|
+
|
153
|
+
it "return no schdules when run interval style is not keep running" do
|
154
|
+
::Naf::ApplicationSchedule.constant_schedules.should == []
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe "#enabled" do
|
159
|
+
it "return empty array when schedule is disabled" do
|
160
|
+
schedule.enabled = false
|
161
|
+
schedule.save!
|
162
|
+
::Naf::ApplicationSchedule.enabled.should == []
|
163
|
+
end
|
164
|
+
|
165
|
+
it "return array with schedule when schedule is enabled" do
|
166
|
+
::Naf::ApplicationSchedule.enabled.should == [schedule]
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "#application_not_deleted" do
|
171
|
+
it "return empty array when application is deleted" do
|
172
|
+
schedule.application.deleted = true
|
173
|
+
schedule.application.save!
|
174
|
+
::Naf::ApplicationSchedule.application_not_deleted.should == []
|
175
|
+
end
|
176
|
+
|
177
|
+
it "return array with schedule when application is not deleted" do
|
178
|
+
::Naf::ApplicationSchedule.application_not_deleted.should == [schedule]
|
179
|
+
end
|
119
180
|
end
|
120
181
|
|
121
182
|
#-------------------------
|
@@ -396,10 +396,12 @@ module Naf
|
|
396
396
|
end
|
397
397
|
|
398
398
|
describe "#affinity" do
|
399
|
+
let!(:classification) { FactoryGirl.create(:machine_affinity_classification) }
|
399
400
|
it "return affinity associated with machine's id" do
|
400
|
-
affinity = FactoryGirl.create(:affinity,
|
401
|
-
|
402
|
-
|
401
|
+
affinity = FactoryGirl.create(:affinity,
|
402
|
+
id: 4,
|
403
|
+
affinity_classification_id: FactoryGirl.create(:machine_affinity_classification).id,
|
404
|
+
affinity_name: machine.id.to_s)
|
403
405
|
machine.affinity.should == affinity
|
404
406
|
end
|
405
407
|
|
metadata
CHANGED
@@ -1,18 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: naf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Keith Gabryelski
|
9
9
|
- Leonardo Meira
|
10
|
-
- Nathaniel Lim
|
11
|
-
- Aleksandr Dembskiy
|
12
10
|
autorequire:
|
13
11
|
bindir: bin
|
14
12
|
cert_chain: []
|
15
|
-
date: 2014-03-
|
13
|
+
date: 2014-03-24 00:00:00.000000000 Z
|
16
14
|
dependencies:
|
17
15
|
- !ruby/object:Gem::Dependency
|
18
16
|
name: rails
|
@@ -239,6 +237,7 @@ files:
|
|
239
237
|
- app/assets/stylesheets/naf.css
|
240
238
|
- app/assets/stylesheets/naf/layout.css.scss
|
241
239
|
- app/controllers/naf/affinities_controller.rb
|
240
|
+
- app/controllers/naf/api_simple_cluster_authenticator_application_controller.rb
|
242
241
|
- app/controllers/naf/application_controller.rb
|
243
242
|
- app/controllers/naf/application_schedule_affinity_tabs_controller.rb
|
244
243
|
- app/controllers/naf/application_schedules_controller.rb
|
@@ -287,6 +286,7 @@ files:
|
|
287
286
|
- app/models/logical/naf/machine_runner_invocation.rb
|
288
287
|
- app/models/logical/naf/pickler.rb
|
289
288
|
- app/models/logical/naf/unpickler.rb
|
289
|
+
- app/models/logical/naf/user_session.rb
|
290
290
|
- app/models/naf/affinity.rb
|
291
291
|
- app/models/naf/affinity_classification.rb
|
292
292
|
- app/models/naf/application.rb
|
@@ -319,6 +319,7 @@ files:
|
|
319
319
|
- app/models/process/naf/data_migration/backfill_application_schedule_run_interval.rb
|
320
320
|
- app/models/process/naf/janitor.rb
|
321
321
|
- app/models/process/naf/log_archiver.rb
|
322
|
+
- app/models/process/naf/log_archiver_queuer.rb
|
322
323
|
- app/models/process/naf/log_reader.rb
|
323
324
|
- app/models/process/naf/logger/base.rb
|
324
325
|
- app/models/process/naf/logger/job_log.rb
|
@@ -485,6 +486,9 @@ files:
|
|
485
486
|
- spec/factories/naf.rb
|
486
487
|
- spec/helpers/naf/application_helper_spec.rb
|
487
488
|
- spec/models/logical/naf/application_spec.rb
|
489
|
+
- spec/models/logical/naf/construction_zone/boss_rspec.rb
|
490
|
+
- spec/models/logical/naf/construction_zone/foreman_spec.rb
|
491
|
+
- spec/models/logical/naf/construction_zone/proletariat_spec.rb
|
488
492
|
- spec/models/logical/naf/construction_zone/work_order_spec.rb
|
489
493
|
- spec/models/logical/naf/job_fetcher_spec.rb
|
490
494
|
- spec/models/logical/naf/job_spec.rb
|
@@ -492,6 +496,7 @@ files:
|
|
492
496
|
- spec/models/logical/naf/machine_runner_invocation_spec.rb
|
493
497
|
- spec/models/logical/naf/machine_runner_spec.rb
|
494
498
|
- spec/models/logical/naf/machine_spec.rb
|
499
|
+
- spec/models/logical/naf/user_session_spec.rb
|
495
500
|
- spec/models/naf/affinity_classification_spec.rb
|
496
501
|
- spec/models/naf/affinity_spec.rb
|
497
502
|
- spec/models/naf/application_run_group_restriction_spec.rb
|
@@ -600,6 +605,9 @@ test_files:
|
|
600
605
|
- spec/factories/naf.rb
|
601
606
|
- spec/helpers/naf/application_helper_spec.rb
|
602
607
|
- spec/models/logical/naf/application_spec.rb
|
608
|
+
- spec/models/logical/naf/construction_zone/boss_rspec.rb
|
609
|
+
- spec/models/logical/naf/construction_zone/foreman_spec.rb
|
610
|
+
- spec/models/logical/naf/construction_zone/proletariat_spec.rb
|
603
611
|
- spec/models/logical/naf/construction_zone/work_order_spec.rb
|
604
612
|
- spec/models/logical/naf/job_fetcher_spec.rb
|
605
613
|
- spec/models/logical/naf/job_spec.rb
|
@@ -607,6 +615,7 @@ test_files:
|
|
607
615
|
- spec/models/logical/naf/machine_runner_invocation_spec.rb
|
608
616
|
- spec/models/logical/naf/machine_runner_spec.rb
|
609
617
|
- spec/models/logical/naf/machine_spec.rb
|
618
|
+
- spec/models/logical/naf/user_session_spec.rb
|
610
619
|
- spec/models/naf/affinity_classification_spec.rb
|
611
620
|
- spec/models/naf/affinity_spec.rb
|
612
621
|
- spec/models/naf/application_run_group_restriction_spec.rb
|