naf 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. data/.gitignore +16 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +17 -0
  4. data/Gemfile +17 -0
  5. data/LICENSE +2 -0
  6. data/README.rdoc +22 -0
  7. data/RELEASE_NOTES.rdoc +18 -0
  8. data/Rakefile +43 -0
  9. data/app/assets/images/bg-grad.png +0 -0
  10. data/app/assets/images/clock.png +0 -0
  11. data/app/assets/images/control_play_blue.png +0 -0
  12. data/app/assets/images/down_arrow.gif +0 -0
  13. data/app/assets/images/papertrail_job.png +0 -0
  14. data/app/assets/images/papertrail_machine.png +0 -0
  15. data/app/assets/images/papertrail_machine_runner.png +0 -0
  16. data/app/assets/images/terminate.png +0 -0
  17. data/app/assets/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  18. data/app/assets/images/ui-bg_flat_0_ffffff_40x100.png +0 -0
  19. data/app/assets/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  20. data/app/assets/images/ui-bg_glass_0_f4f4f4_1x400.png +0 -0
  21. data/app/assets/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  22. data/app/assets/images/ui-bg_glass_65_f4f4f4_1x400.png +0 -0
  23. data/app/assets/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  24. data/app/assets/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  25. data/app/assets/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  26. data/app/assets/images/ui-bg_glass_75_f4f4f4_1x400.png +0 -0
  27. data/app/assets/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  28. data/app/assets/images/ui-bg_highlight-soft_0_f4f4f4_1x100.png +0 -0
  29. data/app/assets/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  30. data/app/assets/images/ui-icons_222222_256x240.png +0 -0
  31. data/app/assets/images/ui-icons_2e83ff_256x240.png +0 -0
  32. data/app/assets/images/ui-icons_454545_256x240.png +0 -0
  33. data/app/assets/images/ui-icons_888888_256x240.png +0 -0
  34. data/app/assets/images/ui-icons_cd0a0a_256x240.png +0 -0
  35. data/app/assets/images/up_arrow.gif +0 -0
  36. data/app/assets/javascripts/dataTablesTemplates/applications.js +94 -0
  37. data/app/assets/javascripts/dataTablesTemplates/jobs.js +163 -0
  38. data/app/assets/javascripts/dataTablesTemplates/machine_runner_invocations.js +60 -0
  39. data/app/assets/javascripts/dataTablesTemplates/machine_runners.js +82 -0
  40. data/app/assets/javascripts/dataTablesTemplates/machines.js +93 -0
  41. data/app/assets/javascripts/date.js +104 -0
  42. data/app/assets/javascripts/iso8601.js +41 -0
  43. data/app/assets/javascripts/jquery.dataTables.custom.js +62 -0
  44. data/app/assets/javascripts/jquery.dataTables.js +6862 -0
  45. data/app/assets/javascripts/naf.js +30 -0
  46. data/app/assets/javascripts/underscore.js +713 -0
  47. data/app/assets/stylesheets/jquery_ui/jquery-ui-1.8.5.custom.css.erb +572 -0
  48. data/app/assets/stylesheets/min_naf.css +14 -0
  49. data/app/assets/stylesheets/min_naf/layout.css.scss +355 -0
  50. data/app/assets/stylesheets/naf.css +14 -0
  51. data/app/assets/stylesheets/naf/layout.css.scss +497 -0
  52. data/app/controllers/naf/affinities_controller.rb +61 -0
  53. data/app/controllers/naf/application_controller.rb +43 -0
  54. data/app/controllers/naf/application_schedule_affinity_tabs_controller.rb +75 -0
  55. data/app/controllers/naf/applications_controller.rb +153 -0
  56. data/app/controllers/naf/historical_job_affinity_tabs_controller.rb +65 -0
  57. data/app/controllers/naf/historical_jobs_controller.rb +159 -0
  58. data/app/controllers/naf/janitorial_assignments_controller.rb +77 -0
  59. data/app/controllers/naf/logger_names_controller.rb +58 -0
  60. data/app/controllers/naf/logger_styles_controller.rb +59 -0
  61. data/app/controllers/naf/machine_affinity_slots_controller.rb +69 -0
  62. data/app/controllers/naf/machine_runner_invocations_controller.rb +59 -0
  63. data/app/controllers/naf/machine_runners_controller.rb +26 -0
  64. data/app/controllers/naf/machines_controller.rb +95 -0
  65. data/app/helpers/naf/application_helper.rb +275 -0
  66. data/app/models/log4r/papertrail_outputter.rb +19 -0
  67. data/app/models/logical/naf/application.rb +183 -0
  68. data/app/models/logical/naf/construction_zone/ad_hoc_work_order.rb +22 -0
  69. data/app/models/logical/naf/construction_zone/application_schedule_work_order.rb +15 -0
  70. data/app/models/logical/naf/construction_zone/application_work_order.rb +25 -0
  71. data/app/models/logical/naf/construction_zone/boss.rb +123 -0
  72. data/app/models/logical/naf/construction_zone/foreman.rb +53 -0
  73. data/app/models/logical/naf/construction_zone/proletariat.rb +40 -0
  74. data/app/models/logical/naf/construction_zone/work_order.rb +100 -0
  75. data/app/models/logical/naf/create_infrastructure.rb +48 -0
  76. data/app/models/logical/naf/job.rb +357 -0
  77. data/app/models/logical/naf/job_creator.rb +155 -0
  78. data/app/models/logical/naf/job_fetcher.rb +167 -0
  79. data/app/models/logical/naf/job_statuses/errored.rb +27 -0
  80. data/app/models/logical/naf/job_statuses/finished.rb +26 -0
  81. data/app/models/logical/naf/job_statuses/finished_less_minute.rb +25 -0
  82. data/app/models/logical/naf/job_statuses/queued.rb +32 -0
  83. data/app/models/logical/naf/job_statuses/running.rb +34 -0
  84. data/app/models/logical/naf/job_statuses/terminated.rb +25 -0
  85. data/app/models/logical/naf/job_statuses/waiting.rb +43 -0
  86. data/app/models/logical/naf/machine.rb +85 -0
  87. data/app/models/logical/naf/machine_runner.rb +46 -0
  88. data/app/models/logical/naf/machine_runner_invocation.rb +50 -0
  89. data/app/models/logical/naf/pickler.rb +74 -0
  90. data/app/models/logical/naf/unpickler.rb +98 -0
  91. data/app/models/naf/affinity.rb +145 -0
  92. data/app/models/naf/affinity_classification.rb +44 -0
  93. data/app/models/naf/application.rb +100 -0
  94. data/app/models/naf/application_run_group_restriction.rb +39 -0
  95. data/app/models/naf/application_schedule.rb +181 -0
  96. data/app/models/naf/application_schedule_affinity_tab.rb +86 -0
  97. data/app/models/naf/application_schedule_prerequisite.rb +50 -0
  98. data/app/models/naf/application_type.rb +72 -0
  99. data/app/models/naf/by_historical_job_id.rb +86 -0
  100. data/app/models/naf/historical_job.rb +334 -0
  101. data/app/models/naf/historical_job_affinity_tab.rb +61 -0
  102. data/app/models/naf/historical_job_prerequisite.rb +19 -0
  103. data/app/models/naf/janitorial_archive_assignment.rb +36 -0
  104. data/app/models/naf/janitorial_assignment.rb +37 -0
  105. data/app/models/naf/janitorial_create_assignment.rb +36 -0
  106. data/app/models/naf/janitorial_drop_assignment.rb +36 -0
  107. data/app/models/naf/logger_level.rb +21 -0
  108. data/app/models/naf/logger_name.rb +23 -0
  109. data/app/models/naf/logger_style.rb +58 -0
  110. data/app/models/naf/logger_style_name.rb +28 -0
  111. data/app/models/naf/machine.rb +257 -0
  112. data/app/models/naf/machine_affinity_slot.rb +78 -0
  113. data/app/models/naf/machine_runner.rb +51 -0
  114. data/app/models/naf/machine_runner_invocation.rb +71 -0
  115. data/app/models/naf/naf_base.rb +9 -0
  116. data/app/models/naf/queued_job.rb +164 -0
  117. data/app/models/naf/running_job.rb +80 -0
  118. data/app/models/process/naf/application.rb +164 -0
  119. data/app/models/process/naf/janitor.rb +117 -0
  120. data/app/models/process/naf/machine_manager.rb +150 -0
  121. data/app/models/process/naf/machine_upgrader.rb +112 -0
  122. data/app/models/process/naf/runner.rb +539 -0
  123. data/app/views/naf/affinities/_form.html.erb +50 -0
  124. data/app/views/naf/affinities/edit.html.erb +11 -0
  125. data/app/views/naf/affinities/index.html.erb +57 -0
  126. data/app/views/naf/affinities/new.html.erb +15 -0
  127. data/app/views/naf/affinities/show.html.erb +48 -0
  128. data/app/views/naf/application_schedule_affinity_tabs/_form.html.erb +31 -0
  129. data/app/views/naf/application_schedule_affinity_tabs/edit.html.erb +12 -0
  130. data/app/views/naf/application_schedule_affinity_tabs/new.html.erb +11 -0
  131. data/app/views/naf/applications/_application_schedule.html.erb +80 -0
  132. data/app/views/naf/applications/_application_schedule_prerequisites.html.erb +14 -0
  133. data/app/views/naf/applications/_form.html.erb +109 -0
  134. data/app/views/naf/applications/_search_container.html.erb +94 -0
  135. data/app/views/naf/applications/_show.html.erb +34 -0
  136. data/app/views/naf/applications/edit.html.erb +11 -0
  137. data/app/views/naf/applications/index.html.erb +51 -0
  138. data/app/views/naf/applications/index.json.erb +11 -0
  139. data/app/views/naf/applications/new.html.erb +11 -0
  140. data/app/views/naf/applications/show.html.erb +203 -0
  141. data/app/views/naf/datatable.html.erb +49 -0
  142. data/app/views/naf/historical_job_affinity_tabs/_form.html.erb +36 -0
  143. data/app/views/naf/historical_job_affinity_tabs/edit.html.erb +11 -0
  144. data/app/views/naf/historical_job_affinity_tabs/new.html.erb +11 -0
  145. data/app/views/naf/historical_jobs/_form.html.erb +94 -0
  146. data/app/views/naf/historical_jobs/_runners.html.erb +22 -0
  147. data/app/views/naf/historical_jobs/_search_container.html.erb +140 -0
  148. data/app/views/naf/historical_jobs/edit.html.erb +11 -0
  149. data/app/views/naf/historical_jobs/index.html.erb +48 -0
  150. data/app/views/naf/historical_jobs/index.json.erb +26 -0
  151. data/app/views/naf/historical_jobs/new.html.erb +61 -0
  152. data/app/views/naf/historical_jobs/show.html.erb +201 -0
  153. data/app/views/naf/janitorial_assignments/_form.html.erb +38 -0
  154. data/app/views/naf/janitorial_assignments/_rows.html.erb +17 -0
  155. data/app/views/naf/janitorial_assignments/edit.html.erb +11 -0
  156. data/app/views/naf/janitorial_assignments/index.html.erb +56 -0
  157. data/app/views/naf/janitorial_assignments/index.js.erb +1 -0
  158. data/app/views/naf/janitorial_assignments/new.html.erb +11 -0
  159. data/app/views/naf/layouts/jquery_datatables.json.erb +6 -0
  160. data/app/views/naf/logger_names/_form.html.erb +18 -0
  161. data/app/views/naf/logger_names/edit.html.erb +11 -0
  162. data/app/views/naf/logger_names/new.html.erb +11 -0
  163. data/app/views/naf/logger_names/show.html.erb +44 -0
  164. data/app/views/naf/logger_styles/_form.html.erb +30 -0
  165. data/app/views/naf/logger_styles/_logger_style_names.html.erb +19 -0
  166. data/app/views/naf/logger_styles/edit.html.erb +11 -0
  167. data/app/views/naf/logger_styles/new.html.erb +11 -0
  168. data/app/views/naf/logger_styles/show.html.erb +48 -0
  169. data/app/views/naf/machine_affinity_slots/_form.html.erb +36 -0
  170. data/app/views/naf/machine_affinity_slots/edit.html.erb +11 -0
  171. data/app/views/naf/machine_affinity_slots/new.html.erb +11 -0
  172. data/app/views/naf/machine_runner_invocations/_filter.html.erb +21 -0
  173. data/app/views/naf/machine_runner_invocations/index.html.erb +36 -0
  174. data/app/views/naf/machine_runner_invocations/index.json.erb +16 -0
  175. data/app/views/naf/machine_runner_invocations/show.html.erb +91 -0
  176. data/app/views/naf/machine_runners/index.html.erb +82 -0
  177. data/app/views/naf/machine_runners/index.json.erb +16 -0
  178. data/app/views/naf/machine_runners/show.html.erb +113 -0
  179. data/app/views/naf/machines/_filter.html.erb +26 -0
  180. data/app/views/naf/machines/_form.html.erb +62 -0
  181. data/app/views/naf/machines/_show.html.erb +169 -0
  182. data/app/views/naf/machines/edit.html.erb +11 -0
  183. data/app/views/naf/machines/index.html.erb +51 -0
  184. data/app/views/naf/machines/index.json.erb +23 -0
  185. data/app/views/naf/machines/new.html.erb +11 -0
  186. data/app/views/naf/machines/show.html.erb +92 -0
  187. data/app/views/naf/record.html.erb +46 -0
  188. data/app/views/naf/shared/_application.html.erb +50 -0
  189. data/app/views/naf/shared/_information_container.html.erb +19 -0
  190. data/app/views/naf/shared/_select_per_page.html.erb +72 -0
  191. data/ci/test-build.sh +17 -0
  192. data/ci/travis.sh +26 -0
  193. data/config/initializers/naf.rb +3 -0
  194. data/config/routes.rb +38 -0
  195. data/db/migrate/20120820023848_naf_schema.rb +413 -0
  196. data/doc/README_FOR_APP +2 -0
  197. data/lib/generators/naf_generator.rb +45 -0
  198. data/lib/generators/templates/config/logging/af.yml +26 -0
  199. data/lib/generators/templates/config/logging/naf.yml +22 -0
  200. data/lib/generators/templates/config/logging/nafjob.yml +16 -0
  201. data/lib/generators/templates/config/logging/nafrunner.yml +17 -0
  202. data/lib/generators/templates/naf.rb +11 -0
  203. data/lib/generators/templates/naf_layout.html.erb +15 -0
  204. data/lib/naf.rb +48 -0
  205. data/lib/naf/configuration.rb +23 -0
  206. data/lib/naf/engine.rb +18 -0
  207. data/lib/naf/version.rb +3 -0
  208. data/lib/tasks/naf_tasks.rake +370 -0
  209. data/naf.gemspec +30 -0
  210. data/script/rails +10 -0
  211. data/spec/controllers/naf/affinities_controller_spec.rb +79 -0
  212. data/spec/controllers/naf/application_controller_spec.rb +10 -0
  213. data/spec/controllers/naf/application_schedule_affinity_tabs_controller_spec.rb +106 -0
  214. data/spec/controllers/naf/applications_controller_spec.rb +109 -0
  215. data/spec/controllers/naf/historical_job_affinity_tabs_controller_spec.rb +96 -0
  216. data/spec/controllers/naf/historical_jobs_controller_spec.rb +19 -0
  217. data/spec/controllers/naf/machine_affinity_slots_controller_spec.rb +109 -0
  218. data/spec/controllers/naf/machines_controller_spec.rb +74 -0
  219. data/spec/dummy/.gitignore +12 -0
  220. data/spec/dummy/README +19 -0
  221. data/spec/dummy/Rakefile +7 -0
  222. data/spec/dummy/app/assets/javascripts/application.js +16 -0
  223. data/spec/dummy/app/assets/stylesheets/application.css +14 -0
  224. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  225. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  226. data/spec/dummy/app/models/my_script.rb +8 -0
  227. data/spec/dummy/app/models/other/base.rb.sample +10 -0
  228. data/spec/dummy/app/views/layouts/application.html.erb +15 -0
  229. data/spec/dummy/app/views/layouts/naf_layout.html.erb +15 -0
  230. data/spec/dummy/config.ru +4 -0
  231. data/spec/dummy/config/application.rb +62 -0
  232. data/spec/dummy/config/boot.rb +10 -0
  233. data/spec/dummy/config/database-non_primary.yml +20 -0
  234. data/spec/dummy/config/database-primary.yml +16 -0
  235. data/spec/dummy/config/environment.rb +5 -0
  236. data/spec/dummy/config/environments/development.rb +37 -0
  237. data/spec/dummy/config/environments/production.rb +67 -0
  238. data/spec/dummy/config/environments/test.rb +37 -0
  239. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  240. data/spec/dummy/config/initializers/inflections.rb +15 -0
  241. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  242. data/spec/dummy/config/initializers/naf.rb.non_primary +4 -0
  243. data/spec/dummy/config/initializers/naf.rb.primary +3 -0
  244. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  245. data/spec/dummy/config/initializers/session_store.rb +8 -0
  246. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  247. data/spec/dummy/config/locales/en.yml +5 -0
  248. data/spec/dummy/config/logging/af.yml +26 -0
  249. data/spec/dummy/config/logging/naf.yml +22 -0
  250. data/spec/dummy/config/logging/nafjob.yml +16 -0
  251. data/spec/dummy/config/logging/nafrunner.yml +17 -0
  252. data/spec/dummy/config/routes.rb +5 -0
  253. data/spec/dummy/db/.gitignore +2 -0
  254. data/spec/dummy/lib/tasks/dummy.rake +60 -0
  255. data/spec/dummy/public/404.html +26 -0
  256. data/spec/dummy/public/422.html +26 -0
  257. data/spec/dummy/public/500.html +25 -0
  258. data/spec/dummy/public/favicon.ico +0 -0
  259. data/spec/dummy/script/rails +6 -0
  260. data/spec/factories/naf.rb +433 -0
  261. data/spec/helpers/naf/application_helper_spec.rb +0 -0
  262. data/spec/models/logical/naf/application_spec.rb +69 -0
  263. data/spec/models/logical/naf/job_creator_spec.rb +32 -0
  264. data/spec/models/logical/naf/job_fetcher_spec.rb +140 -0
  265. data/spec/models/logical/naf/job_spec.rb +282 -0
  266. data/spec/models/logical/naf/machine_spec.rb +61 -0
  267. data/spec/models/naf/affinity_classification_spec.rb +56 -0
  268. data/spec/models/naf/affinity_spec.rb +100 -0
  269. data/spec/models/naf/application_run_group_restriction_spec.rb +57 -0
  270. data/spec/models/naf/application_schedule_affinity_tab_spec.rb +85 -0
  271. data/spec/models/naf/application_schedule_prerequisite_spec.rb +35 -0
  272. data/spec/models/naf/application_schedule_spec.rb +166 -0
  273. data/spec/models/naf/application_spec.rb +128 -0
  274. data/spec/models/naf/application_type_spec.rb +104 -0
  275. data/spec/models/naf/historical_job_affinity_tab_spec.rb +59 -0
  276. data/spec/models/naf/historical_job_prerequisite_spec.rb +25 -0
  277. data/spec/models/naf/historical_job_spec.rb +334 -0
  278. data/spec/models/naf/logger_level_spec.rb +34 -0
  279. data/spec/models/naf/logger_name_spec.rb +35 -0
  280. data/spec/models/naf/logger_style_name_spec.rb +39 -0
  281. data/spec/models/naf/logger_style_spec.rb +89 -0
  282. data/spec/models/naf/machine_affinity_slot_spec.rb +77 -0
  283. data/spec/models/naf/machine_runner_invocation_spec.rb +38 -0
  284. data/spec/models/naf/machine_runner_spec.rb +37 -0
  285. data/spec/models/naf/machine_spec.rb +425 -0
  286. data/spec/models/naf/naf_base_spec.rb +14 -0
  287. data/spec/models/naf/queued_job_spec.rb +171 -0
  288. data/spec/models/naf/running_job_spec.rb +107 -0
  289. data/spec/models/process/naf/application_spec.rb +8 -0
  290. data/spec/models/process/naf/janitor_spec.rb +10 -0
  291. data/spec/models/process/naf/runner_spec.rb +10 -0
  292. data/spec/spec_helper.rb +32 -0
  293. data/spec/support/engine_routing.rb +27 -0
  294. data/spec/support/script_spec_helper.rb +58 -0
  295. metadata +590 -0
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ module Logical
4
+ module Naf
5
+ describe Application do
6
+ let(:columns) { [:id,
7
+ :title,
8
+ :short_name,
9
+ :script_type_name,
10
+ :application_run_group_name,
11
+ :application_run_group_restriction_name,
12
+ :application_run_group_limit,
13
+ :enabled,
14
+ :enqueue_backlogs,
15
+ :run_time,
16
+ :affinities,
17
+ :prerequisites,
18
+ :deleted,
19
+ :visible] }
20
+ let(:physical_app) { FactoryGirl.create(:application) }
21
+ let!(:logical_app) { Application.new(physical_app) }
22
+ let(:scheduled_physical_app) {
23
+ FactoryGirl.create(:scheduled_application, application_schedule: FactoryGirl.create(:schedule_at_time))
24
+ }
25
+
26
+ context "Class Methods" do
27
+ it "search method should return array of wrapper around physical application" do
28
+ app = logical_app
29
+ Application.search(params: nil).map(&:id).should include(app.id)
30
+ Application.search(params: nil).should have(1).items
31
+ Application.search(params: nil).should be_a(Array)
32
+ end
33
+ end
34
+
35
+ it "should delegate command to the physical app" do
36
+ logical_app.should_receive(:command).and_return("")
37
+ logical_app.command
38
+ end
39
+
40
+ it "to_hash should have the specified columns" do
41
+ logical_app.to_hash.keys.should == columns
42
+ end
43
+
44
+ it "should render run_start_minute" do
45
+ scheduled_physical_app.application_schedule.run_start_minute.should be_a(Fixnum)
46
+
47
+ Application.new(scheduled_physical_app).run_start_minute.should be_a(String)
48
+ end
49
+
50
+ it "should delegate methods to its schedule" do
51
+ methods = [:application_run_group_restriction_name,
52
+ :run_interval,
53
+ :application_run_group_name,
54
+ :run_start_minute]
55
+ schedule = scheduled_physical_app.application_schedule
56
+ logical_scheduled_app = Application.new(scheduled_physical_app)
57
+
58
+ methods.each do |m|
59
+ schedule.should_receive(m).and_return(nil)
60
+ end
61
+
62
+ methods.each do |m|
63
+ logical_scheduled_app.send(m)
64
+ end
65
+ end
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ module Logical
4
+ module Naf
5
+ describe JobCreator do
6
+ context "with regard to queuing from an application_schedule" do
7
+ context "a new queued job should get from an application_schedule" do
8
+
9
+ let(:app_schedule_for_canary) {
10
+ tab = FactoryGirl.create(:canary_app_schedule_affinity_tab)
11
+ tab.application_schedule
12
+ }
13
+ let(:job_creator) { JobCreator.new }
14
+
15
+ before do
16
+ ::Naf::HistoricalJob.delete_all
17
+ ::Naf::HistoricalJobAffinityTab.delete_all
18
+ ::Naf::ApplicationSchedule.destroy_all
19
+ app_schedule_for_canary.enqueue_backlogs = true
20
+ end
21
+
22
+ it "affinities" do
23
+ job_creator.queue_application_schedule(app_schedule_for_canary)
24
+ ::Naf::HistoricalJob.first.historical_job_affinity_tabs.map(&:affinity_id).
25
+ should == app_schedule_for_canary.application_schedule_affinity_tabs.map(&:affinity_id)
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,140 @@
1
+ require 'spec_helper'
2
+
3
+ module Logical
4
+ module Naf
5
+ describe JobFetcher do
6
+ let(:job) { FactoryGirl.create(:job) }
7
+ let(:normal_slot) { FactoryGirl.create(:normal_machine_affinity_slot, machine: FactoryGirl.create(:machine)) }
8
+ let(:required_perennial_slot) { FactoryGirl.create(:required_perennial_slot, machine: FactoryGirl.create(:machine_two)) }
9
+ let(:normal_machine) { normal_slot.machine }
10
+ let(:perennial_machine) { required_perennial_slot.machine }
11
+ let(:normal_tab) { FactoryGirl.create(:normal_job_affinity_tab) }
12
+ let(:perennial_tab) { FactoryGirl.create(:perennial_job_affinity_tab) }
13
+ let(:normal_job) { normal_tab.job }
14
+ let(:perennial_job) { perennial_tab.job }
15
+ let(:perennial_job_fetcher) { JobFetcher.new(perennial_machine) }
16
+ let(:normal_job_fetcher) { JobFetcher.new(normal_machine) }
17
+
18
+ before(:all) do
19
+ ::Naf::HistoricalJob.delete_all
20
+ end
21
+
22
+ before do
23
+ ::Naf::MachineAffinitySlot.delete_all
24
+ FactoryGirl.create(:affinity, id: 4, affinity_name: 'cpus')
25
+ FactoryGirl.create(:affinity, id: 5, affinity_name: 'memory')
26
+ end
27
+
28
+ #----------------------------
29
+ # *** Shared Examples ***
30
+ #++++++++++++++++++++++++++++
31
+
32
+ shared_examples "inserts machine affinity slots correctly" do
33
+ it { required_perennial_slot.required.should be_true }
34
+ it { normal_slot.required.should be_false }
35
+ end
36
+
37
+ shared_examples "fetches next job correctly" do
38
+ it "asserts next job is not equal to first job" do
39
+ first_job.should_not == second_job
40
+ end
41
+
42
+ it "insert row correctly into historical_jobs" do
43
+ ::Naf::HistoricalJob.queued_between(Time.zone.now - ::Naf::HistoricalJob::JOB_STALE_TIME, Time.zone.now).
44
+ where(started_at: nil).first.should == first_job
45
+ end
46
+
47
+ it "return correctly next fetched job" do
48
+ FactoryGirl.create(:queued_job, historical_job: second_job)
49
+ fetcher.fetch_next_job.historical_job.should == second_job
50
+ end
51
+ end
52
+
53
+ describe "single affinity" do
54
+ context "jobs that don't have the affinity a machine requires" do
55
+ before do
56
+ job
57
+ perennial_job
58
+ end
59
+
60
+ it "return 0 affinity tabs for first job" do
61
+ job.historical_job_affinity_tabs.should be_empty
62
+ end
63
+
64
+ it_should_behave_like "inserts machine affinity slots correctly"
65
+ it_should_behave_like "fetches next job correctly" do
66
+ let(:first_job) { job }
67
+ let(:second_job) { perennial_job }
68
+ let(:fetcher) { perennial_job_fetcher }
69
+ end
70
+ end
71
+
72
+ context "jobs that the machine doesn't have an affinity for" do
73
+ before do
74
+ perennial_job
75
+ normal_job
76
+ end
77
+
78
+ it_should_behave_like "inserts machine affinity slots correctly"
79
+ it_should_behave_like "fetches next job correctly" do
80
+ let(:first_job) { perennial_job }
81
+ let(:second_job) { normal_job }
82
+ let(:fetcher) { normal_job_fetcher }
83
+ end
84
+ end
85
+ end
86
+
87
+ describe "multiple affinities" do
88
+ let(:canary_machine) {
89
+ slot = FactoryGirl.create(:canary_slot, machine: FactoryGirl.create(:machine))
90
+ slot.machine
91
+ }
92
+ let(:canary_job) {
93
+ tab = FactoryGirl.create(:canary_job_affinity_tab)
94
+ tab.job
95
+ }
96
+ let(:canary_perennial_machine) {
97
+ slot_one = FactoryGirl.create(:required_canary_slot, machine: FactoryGirl.create(:machine_two))
98
+ slot_two = FactoryGirl.create(:required_perennial_slot, machine: FactoryGirl.create(:machine_two))
99
+ slot_two.machine
100
+ }
101
+ let(:canary_perennial_job) {
102
+ first_tab = FactoryGirl.create(:canary_job_affinity_tab)
103
+ second_tab = FactoryGirl.create(:perennial_job_affinity_tab, historical_job: first_tab.job)
104
+ second_tab.job
105
+ }
106
+ let(:canary_job_fetcher) { JobFetcher.new(canary_machine) }
107
+ let(:canary_perennial_job_fetcher) { JobFetcher.new(canary_perennial_machine) }
108
+
109
+ context "jobs that the machine doesn't have an affinity for" do
110
+ before do
111
+ canary_job
112
+ canary_perennial_job
113
+ end
114
+
115
+ it_should_behave_like "inserts machine affinity slots correctly"
116
+ it_should_behave_like "fetches next job correctly" do
117
+ let(:first_job) { canary_job }
118
+ let(:second_job) { canary_perennial_job }
119
+ let(:fetcher) { canary_perennial_job_fetcher }
120
+ end
121
+ end
122
+
123
+ context "jobs that the machine doesn't have one affinity for" do
124
+ before do
125
+ canary_perennial_job
126
+ canary_job
127
+ end
128
+
129
+ it_should_behave_like "inserts machine affinity slots correctly"
130
+ it_should_behave_like "fetches next job correctly" do
131
+ let(:first_job) { canary_perennial_job }
132
+ let(:second_job) { canary_job }
133
+ let(:fetcher) { canary_job_fetcher }
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ end
140
+ end
@@ -0,0 +1,282 @@
1
+ require 'spec_helper'
2
+
3
+ module Logical
4
+ module Naf
5
+ describe Job do
6
+
7
+ TIME_DISPLAY_REGEX = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} (AM|PM)$/
8
+
9
+ STATUS_MAP = {
10
+ job: "Queued",
11
+ canceled_job: "Terminated",
12
+ terminating_job: "Terminating",
13
+ running_job: "Running",
14
+ failed_to_start_job: "Failed to Start",
15
+ finished_job: "Finished",
16
+ job_with_error: "Error 1",
17
+ job_with_signal: "Signaled 1"
18
+ }
19
+
20
+ let!(:job) { Job.new(FactoryGirl.create(:finished_job)) }
21
+ let!(:historical_job) { job.instance_variable_get(:@job) }
22
+
23
+ it "should return the correct statuses" do
24
+ STATUS_MAP.each do |job_type, expected_status|
25
+ logical_job = Job.new(FactoryGirl.create(job_type))
26
+ logical_job.status.should eql(expected_status)
27
+ end
28
+ end
29
+
30
+ context "#title" do
31
+ let(:scheduled_job) { Job.new(FactoryGirl.create(:scheduled_job)) }
32
+
33
+ context "for a job scheduled from an application" do
34
+ it "should get the title from the application_schedule" do
35
+ scheduled_job.title.should eql(scheduled_job.application.title)
36
+ end
37
+ end
38
+
39
+ context "for an ad hoc job" do
40
+ it "should get the title, formed from its command" do
41
+ job = Job.new(FactoryGirl.create(:job, command: "Yo"*30))
42
+ job.title.should eql(job.command)
43
+ end
44
+ end
45
+ end
46
+
47
+ context "with regard to the timestamps" do
48
+ it "should display started_at nicely" do
49
+ job.started_at.should be_a(String)
50
+ job.started_at.should =~ /-0h3m/
51
+ end
52
+
53
+ it "should display finished_at nicely" do
54
+ job.finished_at.should be_a(String)
55
+ job.finished_at.split(',').first.should =~ /ago$/
56
+ end
57
+
58
+ it "should display queued time explicitly as string" do
59
+ job.queued_time.should be_a(String)
60
+ job.queued_time.should =~ TIME_DISPLAY_REGEX
61
+ end
62
+ end
63
+
64
+ context "#to_detailed_hash" do
65
+ let(:detailed_hash) { Job.new(FactoryGirl.create(:finished_job)).to_detailed_hash }
66
+
67
+ it "should display started_at, and finished_at explicitly as a string" do
68
+ [:started_at, :finished_at].each do |timestamp|
69
+ detailed_hash[timestamp].should be_a String
70
+ detailed_hash[timestamp].should =~ TIME_DISPLAY_REGEX
71
+ end
72
+ end
73
+ end
74
+
75
+ context "#to_hash" do
76
+ let(:columns) {
77
+ [:id,
78
+ :server,
79
+ :pid,
80
+ :queued_time,
81
+ :title,
82
+ :started_at,
83
+ :finished_at,
84
+ :run_time,
85
+ :affinities,
86
+ :tags,
87
+ :status] }
88
+
89
+ it "should have the following columns" do
90
+ job.to_hash.keys.should. == columns
91
+ end
92
+ end
93
+
94
+ context "#search" do
95
+ before(:all) do
96
+ ::Naf::HistoricalJob.delete_all
97
+ @job_status_type_map = {}
98
+ STATUS_MAP.each{ |factory, status|
99
+ @job_status_type_map[status.downcase.split(' ').join('_')] = Job.new(FactoryGirl.create(factory))
100
+ }
101
+ end
102
+
103
+ it "should filter by status correctly" do
104
+ @job_status_type_map.each do |status, logical_job|
105
+ Job.search(status: status, limit: 10).map(&:id).should include(logical_job.id)
106
+ end
107
+ end
108
+
109
+ it "should not filter by status when 'all' is specified" do
110
+ job_ids = @job_status_type_map.values.map(&:id)
111
+ result_ids = Job.search(status: 'all', limit: 10).map(&:id)
112
+ job_ids.each do |job_id|
113
+ result_ids.should include job_id
114
+ end
115
+ end
116
+
117
+ context "for other filtering and searching" do
118
+ let(:job_one) { FactoryGirl.create(:running_job,
119
+ pid: 400,
120
+ command: "MyScript.run --thing friend") }
121
+ let(:job_two) { FactoryGirl.create(:running_job,
122
+ application_type: FactoryGirl.create(:bash_command_app_type),
123
+ pid: 500,
124
+ command: "ps aux | grep ssh",
125
+ priority: 5,
126
+ application_run_group_restriction: FactoryGirl.create(:limited_per_machine),
127
+ application_run_group_name: "crazy group") }
128
+
129
+ before do
130
+ ::Naf::HistoricalJob.delete_all
131
+ job_one
132
+ job_two
133
+ ::Naf::HistoricalJob.all.should have(2).items
134
+ end
135
+
136
+ it "should filter by application type" do
137
+ id_one = job_one.application_type_id
138
+ Job.search(application_type_id: id_one, limit: 10).map(&:id).should == [job_one.id]
139
+ id_two = job_two.application_type_id
140
+ Job.search(application_type_id: id_two, limit: 10).map(&:id).should == [job_two.id]
141
+ end
142
+
143
+ it "should filter by run_group_restriction" do
144
+ id_one = job_one.application_run_group_restriction_id
145
+ Job.search(application_run_group_restriction_id: id_one, limit: 10).map(&:id).should == [job_one.id]
146
+ id_two = job_two.application_run_group_restriction_id
147
+ Job.search(application_run_group_restriction_id: id_two, limit: 10).map(&:id).should == [job_two.id]
148
+ end
149
+
150
+ it "should filter by priority" do
151
+ priority_one = job_one.priority
152
+ Job.search(priority: priority_one, limit: 10).map(&:id).should == [job_one.id]
153
+ priority_two = job_two.priority
154
+ Job.search(priority: priority_two, limit: 10).map(&:id).should == [job_two.id]
155
+ end
156
+
157
+ it "should filter by pid" do
158
+ pid_one = job_one.pid
159
+ Job.search(pid: pid_one, limit: 10).map(&:id).should == [job_one.id]
160
+ pid_two = job_two.pid
161
+ Job.search(pid: pid_two, limit: 10).map(&:id).should == [job_two.id]
162
+ end
163
+
164
+ it "should find jobs where the command is like the query" do
165
+ Job.search(command: "friend", limit: 10).map(&:id).should == [job_one.id]
166
+ Job.search(command: "ssh", limit: 10).map(&:id).should == [job_two.id]
167
+ end
168
+
169
+ it "should find jobs where the application_run_group_name is like the query" do
170
+ Job.search(application_run_group_name: "crazy", limit: 10).map(&:id).should == [job_two.id]
171
+ end
172
+ end
173
+ end
174
+
175
+ describe "#get_job_scope" do
176
+ before do
177
+ ::Naf::HistoricalJob.delete_all
178
+ end
179
+ let!(:finished_job) { FactoryGirl.create(:finished_job) }
180
+
181
+ it "return correct job when scope is specified" do
182
+ ::Logical::Naf::Job.get_job_scope({ status: :finished }).should == [finished_job]
183
+ end
184
+
185
+ it "return correct jobs when scope is not specified" do
186
+ historical_job = FactoryGirl.create(:job)
187
+ ::Logical::Naf::Job.get_job_scope({}).should == [finished_job, historical_job]
188
+ end
189
+ end
190
+
191
+ describe "#run_time" do
192
+ before do
193
+ Timecop.freeze(Time.zone.now)
194
+ end
195
+
196
+ after do
197
+ Timecop.return
198
+ end
199
+
200
+ it "show correct run time when job has finished" do
201
+ historical_job.started_at = Time.zone.now - 6.seconds
202
+ historical_job.finished_at = Time.zone.now
203
+ job.run_time.should == '0h0m6s'
204
+ end
205
+
206
+ it "show correct run time when job is running" do
207
+ historical_job.started_at = Time.zone.now - 3.seconds
208
+ historical_job.finished_at = nil
209
+ job.run_time.should == '0h0m3s'
210
+ end
211
+
212
+ it "show correct run time when job has not started" do
213
+ historical_job.started_at = nil
214
+ historical_job.finished_at = nil
215
+ job.run_time.should == ''
216
+ end
217
+ end
218
+
219
+ describe "#started_at" do
220
+ before do
221
+ Timecop.freeze(Time.zone.now)
222
+ end
223
+
224
+ after do
225
+ Timecop.return
226
+ end
227
+
228
+ it "show correct run time when job has started < 60 seconds ago" do
229
+ historical_job.started_at = Time.zone.now - 10.seconds
230
+ job.started_at.should =~ /10 seconds ago/
231
+ end
232
+
233
+ it "show correct run time when job has started >= 60 seconds and < 2 days ago" do
234
+ historical_job.started_at = Time.zone.now - 6.hours
235
+ job.started_at.should =~ /-6h0m/
236
+ end
237
+
238
+ it "show correct run time when job has started <= 2 days ago" do
239
+ historical_job.started_at = Time.zone.now - 3.days
240
+ job.started_at.should =~ /3 days ago/
241
+ end
242
+ end
243
+
244
+ describe "#finished_at" do
245
+ before do
246
+ Timecop.freeze(Time.zone.now)
247
+ end
248
+
249
+ after do
250
+ Timecop.return
251
+ end
252
+
253
+ it "show correct run time when job has finished" do
254
+ historical_job.finished_at = Time.zone.now - 3.seconds
255
+ job.finished_at.should =~ /less than 5 seconds ago/
256
+ end
257
+
258
+ it "show correct run time when job has not finished" do
259
+ historical_job.finished_at = nil
260
+ job.finished_at.should == ''
261
+ end
262
+ end
263
+
264
+ describe "#tags" do
265
+ it "show custom visible tags" do
266
+ historical_job.tags = '{test}'
267
+ job.tags.should == 'test'
268
+ end
269
+
270
+ it "not show system or custom invisible tags" do
271
+ historical_job.tags = '{$test,_test}'
272
+ job.tags.should == ''
273
+ end
274
+
275
+ it "return nil when tags is not present" do
276
+ job.tags.should == nil
277
+ end
278
+ end
279
+
280
+ end
281
+ end
282
+ end