naf 2.1.6 → 2.1.8
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.
- 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
|