flapjack 1.6.0 → 2.0.0b1

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 (301) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -6
  3. data/.gitmodules +1 -1
  4. data/.rspec +1 -1
  5. data/.ruby-version +1 -1
  6. data/.travis.yml +12 -13
  7. data/CHANGELOG.md +2 -9
  8. data/CONTRIBUTING.md +7 -2
  9. data/Gemfile +4 -13
  10. data/LICENCE +1 -0
  11. data/README.md +8 -2
  12. data/Rakefile +2 -2
  13. data/bin/flapjack +3 -12
  14. data/build.sh +4 -2
  15. data/etc/flapjack_config.toml.example +273 -0
  16. data/features/ack_after_sched_maint.feature +18 -21
  17. data/features/cli.feature +11 -71
  18. data/features/cli_flapjack-feed-events.feature +14 -15
  19. data/features/cli_flapjack-nagios-receiver.feature +12 -41
  20. data/features/cli_flapper.feature +12 -41
  21. data/features/cli_purge.feature +5 -6
  22. data/features/cli_receive-events.feature +6 -7
  23. data/features/cli_simulate-failed-check.feature +5 -6
  24. data/features/events.feature +206 -181
  25. data/features/events_check_names.feature +4 -7
  26. data/features/notification_rules.feature +144 -223
  27. data/features/notifications.feature +65 -57
  28. data/features/rollup.feature +45 -47
  29. data/features/steps/cli_steps.rb +4 -5
  30. data/features/steps/events_steps.rb +163 -373
  31. data/features/steps/notifications_steps.rb +408 -264
  32. data/features/steps/packaging-lintian_steps.rb +0 -4
  33. data/features/steps/time_travel_steps.rb +0 -26
  34. data/features/support/daemons.rb +6 -31
  35. data/features/support/env.rb +65 -74
  36. data/flapjack.gemspec +22 -24
  37. data/lib/flapjack.rb +14 -7
  38. data/lib/flapjack/cli/flapper.rb +74 -173
  39. data/lib/flapjack/cli/maintenance.rb +278 -109
  40. data/lib/flapjack/cli/migrate.rb +950 -0
  41. data/lib/flapjack/cli/purge.rb +19 -22
  42. data/lib/flapjack/cli/receiver.rb +150 -326
  43. data/lib/flapjack/cli/server.rb +8 -235
  44. data/lib/flapjack/cli/simulate.rb +42 -57
  45. data/lib/flapjack/configuration.rb +51 -37
  46. data/lib/flapjack/coordinator.rb +138 -129
  47. data/lib/flapjack/data/acknowledgement.rb +177 -0
  48. data/lib/flapjack/data/alert.rb +97 -158
  49. data/lib/flapjack/data/check.rb +611 -0
  50. data/lib/flapjack/data/condition.rb +70 -0
  51. data/lib/flapjack/data/contact.rb +226 -456
  52. data/lib/flapjack/data/event.rb +96 -184
  53. data/lib/flapjack/data/extensions/associations.rb +59 -0
  54. data/lib/flapjack/data/extensions/short_name.rb +25 -0
  55. data/lib/flapjack/data/medium.rb +428 -0
  56. data/lib/flapjack/data/metrics.rb +194 -0
  57. data/lib/flapjack/data/notification.rb +22 -281
  58. data/lib/flapjack/data/rule.rb +473 -0
  59. data/lib/flapjack/data/scheduled_maintenance.rb +244 -0
  60. data/lib/flapjack/data/state.rb +221 -0
  61. data/lib/flapjack/data/statistic.rb +112 -0
  62. data/lib/flapjack/data/tag.rb +277 -0
  63. data/lib/flapjack/data/test_notification.rb +182 -0
  64. data/lib/flapjack/data/unscheduled_maintenance.rb +159 -0
  65. data/lib/flapjack/data/validators/id_validator.rb +20 -0
  66. data/lib/flapjack/exceptions.rb +6 -0
  67. data/lib/flapjack/filters/acknowledgement.rb +23 -16
  68. data/lib/flapjack/filters/base.rb +0 -5
  69. data/lib/flapjack/filters/delays.rb +53 -43
  70. data/lib/flapjack/filters/ok.rb +23 -14
  71. data/lib/flapjack/filters/scheduled_maintenance.rb +3 -3
  72. data/lib/flapjack/filters/unscheduled_maintenance.rb +12 -3
  73. data/lib/flapjack/gateways/aws_sns.rb +65 -49
  74. data/lib/flapjack/gateways/aws_sns/alert.text.erb +2 -2
  75. data/lib/flapjack/gateways/aws_sns/alert_subject.text.erb +2 -2
  76. data/lib/flapjack/gateways/aws_sns/rollup_subject.text.erb +1 -1
  77. data/lib/flapjack/gateways/email.rb +107 -90
  78. data/lib/flapjack/gateways/email/alert.html.erb +19 -18
  79. data/lib/flapjack/gateways/email/alert.text.erb +20 -14
  80. data/lib/flapjack/gateways/email/alert_subject.text.erb +2 -1
  81. data/lib/flapjack/gateways/email/rollup.html.erb +14 -13
  82. data/lib/flapjack/gateways/email/rollup.text.erb +13 -10
  83. data/lib/flapjack/gateways/jabber.rb +679 -671
  84. data/lib/flapjack/gateways/jabber/alert.text.erb +9 -6
  85. data/lib/flapjack/gateways/jsonapi.rb +164 -350
  86. data/lib/flapjack/gateways/jsonapi/data/join_descriptor.rb +44 -0
  87. data/lib/flapjack/gateways/jsonapi/data/method_descriptor.rb +21 -0
  88. data/lib/flapjack/gateways/jsonapi/helpers/headers.rb +63 -0
  89. data/lib/flapjack/gateways/jsonapi/helpers/miscellaneous.rb +136 -0
  90. data/lib/flapjack/gateways/jsonapi/helpers/resources.rb +227 -0
  91. data/lib/flapjack/gateways/jsonapi/helpers/serialiser.rb +313 -0
  92. data/lib/flapjack/gateways/jsonapi/helpers/swagger_docs.rb +322 -0
  93. data/lib/flapjack/gateways/jsonapi/methods/association_delete.rb +115 -0
  94. data/lib/flapjack/gateways/jsonapi/methods/association_get.rb +288 -0
  95. data/lib/flapjack/gateways/jsonapi/methods/association_patch.rb +178 -0
  96. data/lib/flapjack/gateways/jsonapi/methods/association_post.rb +116 -0
  97. data/lib/flapjack/gateways/jsonapi/methods/metrics.rb +71 -0
  98. data/lib/flapjack/gateways/jsonapi/methods/resource_delete.rb +119 -0
  99. data/lib/flapjack/gateways/jsonapi/methods/resource_get.rb +186 -0
  100. data/lib/flapjack/gateways/jsonapi/methods/resource_patch.rb +239 -0
  101. data/lib/flapjack/gateways/jsonapi/methods/resource_post.rb +197 -0
  102. data/lib/flapjack/gateways/jsonapi/middleware/array_param_fixer.rb +27 -0
  103. data/lib/flapjack/gateways/jsonapi/{rack → middleware}/json_params_parser.rb +7 -6
  104. data/lib/flapjack/gateways/jsonapi/middleware/request_timestamp.rb +18 -0
  105. data/lib/flapjack/gateways/oobetet.rb +222 -170
  106. data/lib/flapjack/gateways/pager_duty.rb +388 -0
  107. data/lib/flapjack/gateways/pager_duty/alert.text.erb +13 -0
  108. data/lib/flapjack/gateways/slack.rb +56 -48
  109. data/lib/flapjack/gateways/slack/alert.text.erb +1 -1
  110. data/lib/flapjack/gateways/slack/rollup.text.erb +1 -1
  111. data/lib/flapjack/gateways/sms_aspsms.rb +155 -0
  112. data/lib/flapjack/gateways/sms_aspsms/alert.text.erb +7 -0
  113. data/lib/flapjack/gateways/sms_aspsms/rollup.text.erb +2 -0
  114. data/lib/flapjack/gateways/sms_messagenet.rb +77 -57
  115. data/lib/flapjack/gateways/sms_messagenet/alert.text.erb +3 -2
  116. data/lib/flapjack/gateways/sms_nexmo.rb +53 -51
  117. data/lib/flapjack/gateways/sms_nexmo/alert.text.erb +2 -2
  118. data/lib/flapjack/gateways/sms_nexmo/rollup.text.erb +1 -1
  119. data/lib/flapjack/gateways/sms_twilio.rb +79 -62
  120. data/lib/flapjack/gateways/sms_twilio/alert.text.erb +3 -2
  121. data/lib/flapjack/gateways/web.rb +437 -345
  122. data/lib/flapjack/gateways/web/middleware/request_timestamp.rb +18 -0
  123. data/lib/flapjack/gateways/web/public/css/bootstrap.css +3793 -4340
  124. data/lib/flapjack/gateways/web/public/css/bootstrap.css.map +1 -0
  125. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.eot +0 -0
  126. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.svg +273 -214
  127. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  128. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.woff +0 -0
  129. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.woff2 +0 -0
  130. data/lib/flapjack/gateways/web/public/js/bootstrap.js +1637 -1607
  131. data/lib/flapjack/gateways/web/public/js/self_stats.js +1 -2
  132. data/lib/flapjack/gateways/web/views/_pagination.html.erb +19 -0
  133. data/lib/flapjack/gateways/web/views/check.html.erb +159 -121
  134. data/lib/flapjack/gateways/web/views/checks.html.erb +82 -41
  135. data/lib/flapjack/gateways/web/views/contact.html.erb +59 -71
  136. data/lib/flapjack/gateways/web/views/contacts.html.erb +32 -8
  137. data/lib/flapjack/gateways/web/views/index.html.erb +2 -2
  138. data/lib/flapjack/gateways/web/views/{layout.erb → layout.html.erb} +7 -23
  139. data/lib/flapjack/gateways/web/views/self_stats.html.erb +32 -33
  140. data/lib/flapjack/gateways/web/views/tag.html.erb +32 -0
  141. data/lib/flapjack/gateways/web/views/tags.html.erb +51 -0
  142. data/lib/flapjack/logger.rb +34 -3
  143. data/lib/flapjack/notifier.rb +180 -112
  144. data/lib/flapjack/patches.rb +8 -63
  145. data/lib/flapjack/pikelet.rb +185 -143
  146. data/lib/flapjack/processor.rb +323 -191
  147. data/lib/flapjack/record_queue.rb +33 -0
  148. data/lib/flapjack/redis_proxy.rb +66 -0
  149. data/lib/flapjack/utility.rb +21 -15
  150. data/lib/flapjack/version.rb +2 -1
  151. data/libexec/httpbroker.go +218 -14
  152. data/libexec/oneoff.go +13 -10
  153. data/spec/lib/flapjack/configuration_spec.rb +286 -0
  154. data/spec/lib/flapjack/coordinator_spec.rb +103 -157
  155. data/spec/lib/flapjack/data/check_spec.rb +175 -0
  156. data/spec/lib/flapjack/data/contact_spec.rb +26 -349
  157. data/spec/lib/flapjack/data/event_spec.rb +76 -291
  158. data/spec/lib/flapjack/data/medium_spec.rb +19 -0
  159. data/spec/lib/flapjack/data/rule_spec.rb +43 -0
  160. data/spec/lib/flapjack/data/scheduled_maintenance_spec.rb +976 -0
  161. data/spec/lib/flapjack/data/unscheduled_maintenance_spec.rb +34 -0
  162. data/spec/lib/flapjack/gateways/aws_sns_spec.rb +111 -60
  163. data/spec/lib/flapjack/gateways/email_spec.rb +194 -161
  164. data/spec/lib/flapjack/gateways/jabber_spec.rb +961 -162
  165. data/spec/lib/flapjack/gateways/jsonapi/methods/check_links_spec.rb +155 -0
  166. data/spec/lib/flapjack/gateways/jsonapi/methods/checks_spec.rb +426 -0
  167. data/spec/lib/flapjack/gateways/jsonapi/methods/contact_links_spec.rb +217 -0
  168. data/spec/lib/flapjack/gateways/jsonapi/methods/contacts_spec.rb +425 -0
  169. data/spec/lib/flapjack/gateways/jsonapi/methods/events_spec.rb +271 -0
  170. data/spec/lib/flapjack/gateways/jsonapi/methods/media_spec.rb +257 -0
  171. data/spec/lib/flapjack/gateways/jsonapi/methods/medium_links_spec.rb +163 -0
  172. data/spec/lib/flapjack/gateways/jsonapi/methods/metrics_spec.rb +8 -0
  173. data/spec/lib/flapjack/gateways/jsonapi/methods/rule_links_spec.rb +212 -0
  174. data/spec/lib/flapjack/gateways/jsonapi/methods/rules_spec.rb +289 -0
  175. data/spec/lib/flapjack/gateways/jsonapi/methods/scheduled_maintenance_links_spec.rb +49 -0
  176. data/spec/lib/flapjack/gateways/jsonapi/methods/scheduled_maintenances_spec.rb +242 -0
  177. data/spec/lib/flapjack/gateways/jsonapi/methods/tag_links_spec.rb +274 -0
  178. data/spec/lib/flapjack/gateways/jsonapi/methods/tags_spec.rb +302 -0
  179. data/spec/lib/flapjack/gateways/jsonapi/methods/unscheduled_maintenance_links_spec.rb +49 -0
  180. data/spec/lib/flapjack/gateways/jsonapi/methods/unscheduled_maintenances_spec.rb +339 -0
  181. data/spec/lib/flapjack/gateways/jsonapi_spec.rb +1 -1
  182. data/spec/lib/flapjack/gateways/oobetet_spec.rb +151 -79
  183. data/spec/lib/flapjack/gateways/pager_duty_spec.rb +353 -0
  184. data/spec/lib/flapjack/gateways/slack_spec.rb +53 -53
  185. data/spec/lib/flapjack/gateways/sms_aspsms_spec.rb +106 -0
  186. data/spec/lib/flapjack/gateways/sms_messagenet_spec.rb +111 -54
  187. data/spec/lib/flapjack/gateways/sms_nexmo_spec.rb +50 -51
  188. data/spec/lib/flapjack/gateways/sms_twilio_spec.rb +108 -48
  189. data/spec/lib/flapjack/gateways/web_spec.rb +144 -216
  190. data/spec/lib/flapjack/notifier_spec.rb +132 -1
  191. data/spec/lib/flapjack/pikelet_spec.rb +111 -50
  192. data/spec/lib/flapjack/processor_spec.rb +210 -40
  193. data/spec/lib/flapjack/redis_proxy_spec.rb +45 -0
  194. data/spec/lib/flapjack/utility_spec.rb +11 -15
  195. data/spec/service_consumers/fixture_data.rb +547 -0
  196. data/spec/service_consumers/pact_helper.rb +21 -32
  197. data/spec/service_consumers/pacts/flapjack-diner_v2.0.json +4652 -0
  198. data/spec/service_consumers/provider_states_for_flapjack-diner.rb +279 -322
  199. data/spec/service_consumers/provider_support.rb +8 -0
  200. data/spec/spec_helper.rb +34 -44
  201. data/spec/support/erb_view_helper.rb +1 -1
  202. data/spec/support/factories.rb +58 -0
  203. data/spec/support/jsonapi_helper.rb +15 -26
  204. data/spec/support/mock_logger.rb +43 -0
  205. data/spec/support/xmpp_comparable.rb +24 -0
  206. data/src/flapjack/transport_test.go +30 -1
  207. data/tasks/dump_keys.rake +82 -0
  208. data/tasks/events.rake +7 -7
  209. data/tasks/support/flapjack_config_benchmark.toml +28 -0
  210. data/tasks/support/flapjack_config_benchmark.yaml +0 -2
  211. metadata +175 -222
  212. data/Guardfile +0 -14
  213. data/etc/flapjack_config.yaml.example +0 -477
  214. data/features/cli_flapjack-populator.feature +0 -90
  215. data/features/support/silent_system.rb +0 -4
  216. data/lib/flapjack/cli/import.rb +0 -108
  217. data/lib/flapjack/data/entity.rb +0 -652
  218. data/lib/flapjack/data/entity_check.rb +0 -1044
  219. data/lib/flapjack/data/message.rb +0 -56
  220. data/lib/flapjack/data/migration.rb +0 -234
  221. data/lib/flapjack/data/notification_rule.rb +0 -425
  222. data/lib/flapjack/data/semaphore.rb +0 -44
  223. data/lib/flapjack/data/tagged.rb +0 -48
  224. data/lib/flapjack/gateways/jsonapi/check_methods.rb +0 -206
  225. data/lib/flapjack/gateways/jsonapi/check_presenter.rb +0 -221
  226. data/lib/flapjack/gateways/jsonapi/contact_methods.rb +0 -186
  227. data/lib/flapjack/gateways/jsonapi/entity_methods.rb +0 -223
  228. data/lib/flapjack/gateways/jsonapi/medium_methods.rb +0 -185
  229. data/lib/flapjack/gateways/jsonapi/metrics_methods.rb +0 -132
  230. data/lib/flapjack/gateways/jsonapi/notification_rule_methods.rb +0 -141
  231. data/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb +0 -139
  232. data/lib/flapjack/gateways/jsonapi/report_methods.rb +0 -146
  233. data/lib/flapjack/gateways/pagerduty.rb +0 -318
  234. data/lib/flapjack/gateways/pagerduty/alert.text.erb +0 -10
  235. data/lib/flapjack/gateways/web/public/css/select2-bootstrap.css +0 -87
  236. data/lib/flapjack/gateways/web/public/css/select2.css +0 -615
  237. data/lib/flapjack/gateways/web/public/css/tablesort.css +0 -67
  238. data/lib/flapjack/gateways/web/public/img/select2-spinner.gif +0 -0
  239. data/lib/flapjack/gateways/web/public/img/select2.png +0 -0
  240. data/lib/flapjack/gateways/web/public/img/select2x2.png +0 -0
  241. data/lib/flapjack/gateways/web/public/js/backbone.js +0 -1581
  242. data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +0 -322
  243. data/lib/flapjack/gateways/web/public/js/flapjack.js +0 -82
  244. data/lib/flapjack/gateways/web/public/js/jquery.tablesorter.js +0 -1640
  245. data/lib/flapjack/gateways/web/public/js/jquery.tablesorter.widgets.js +0 -1390
  246. data/lib/flapjack/gateways/web/public/js/modules/contact.js +0 -520
  247. data/lib/flapjack/gateways/web/public/js/modules/entity.js +0 -28
  248. data/lib/flapjack/gateways/web/public/js/modules/medium.js +0 -40
  249. data/lib/flapjack/gateways/web/public/js/select2.js +0 -3397
  250. data/lib/flapjack/gateways/web/public/js/tablesort.js +0 -44
  251. data/lib/flapjack/gateways/web/public/js/underscore.js +0 -1276
  252. data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +0 -173
  253. data/lib/flapjack/gateways/web/views/entities.html.erb +0 -30
  254. data/lib/flapjack/gateways/web/views/entity.html.erb +0 -51
  255. data/lib/flapjack/rack_logger.rb +0 -47
  256. data/lib/flapjack/redis_pool.rb +0 -42
  257. data/spec/lib/flapjack/data/entity_check_spec.rb +0 -1418
  258. data/spec/lib/flapjack/data/entity_spec.rb +0 -872
  259. data/spec/lib/flapjack/data/message_spec.rb +0 -30
  260. data/spec/lib/flapjack/data/migration_spec.rb +0 -104
  261. data/spec/lib/flapjack/data/notification_rule_spec.rb +0 -232
  262. data/spec/lib/flapjack/data/notification_spec.rb +0 -53
  263. data/spec/lib/flapjack/data/semaphore_spec.rb +0 -24
  264. data/spec/lib/flapjack/filters/acknowledgement_spec.rb +0 -6
  265. data/spec/lib/flapjack/filters/delays_spec.rb +0 -6
  266. data/spec/lib/flapjack/filters/ok_spec.rb +0 -6
  267. data/spec/lib/flapjack/filters/scheduled_maintenance_spec.rb +0 -6
  268. data/spec/lib/flapjack/filters/unscheduled_maintenance_spec.rb +0 -6
  269. data/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb +0 -315
  270. data/spec/lib/flapjack/gateways/jsonapi/check_presenter_spec.rb +0 -223
  271. data/spec/lib/flapjack/gateways/jsonapi/contact_methods_spec.rb +0 -131
  272. data/spec/lib/flapjack/gateways/jsonapi/entity_methods_spec.rb +0 -389
  273. data/spec/lib/flapjack/gateways/jsonapi/medium_methods_spec.rb +0 -231
  274. data/spec/lib/flapjack/gateways/jsonapi/notification_rule_methods_spec.rb +0 -169
  275. data/spec/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods_spec.rb +0 -114
  276. data/spec/lib/flapjack/gateways/jsonapi/report_methods_spec.rb +0 -590
  277. data/spec/lib/flapjack/gateways/pagerduty_spec.rb +0 -249
  278. data/spec/lib/flapjack/gateways/web/views/check.html.erb_spec.rb +0 -21
  279. data/spec/lib/flapjack/gateways/web/views/contact.html.erb_spec.rb +0 -24
  280. data/spec/lib/flapjack/gateways/web/views/index.html.erb_spec.rb +0 -16
  281. data/spec/lib/flapjack/redis_pool_spec.rb +0 -29
  282. data/spec/service_consumers/pacts/flapjack-diner_v1.0.json +0 -4702
  283. data/tasks/entities.rake +0 -151
  284. data/tasks/profile.rake +0 -282
  285. data/tmp/acknowledge.rb +0 -13
  286. data/tmp/create_config_yaml.rb +0 -16
  287. data/tmp/create_event_ok.rb +0 -30
  288. data/tmp/create_event_unknown.rb +0 -30
  289. data/tmp/create_events_failure.rb +0 -34
  290. data/tmp/create_events_ok.rb +0 -32
  291. data/tmp/create_events_ok_fail_ack_ok.rb +0 -53
  292. data/tmp/create_events_ok_failure.rb +0 -41
  293. data/tmp/create_events_ok_failure_ack.rb +0 -53
  294. data/tmp/dummy_contacts.json +0 -43
  295. data/tmp/dummy_entities.json +0 -37
  296. data/tmp/generate_nagios_test_hosts.rb +0 -16
  297. data/tmp/notification_rules.rb +0 -73
  298. data/tmp/parse_config_yaml.rb +0 -7
  299. data/tmp/redis_find_spurious_unknown_states.rb +0 -52
  300. data/tmp/test_json_post.rb +0 -19
  301. data/tmp/test_notification_rules_api.rb +0 -171
@@ -1,172 +1,125 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'eventmachine'
4
- require 'em-synchrony'
5
-
3
+ require 'monitor'
6
4
  require 'syslog'
7
5
 
6
+ require 'zermelo'
7
+
8
8
  require 'flapjack/configuration'
9
9
  require 'flapjack/patches'
10
- require 'flapjack/redis_pool'
11
10
 
12
- require 'flapjack/logger'
11
+ require 'flapjack/redis_proxy'
12
+
13
13
  require 'flapjack/pikelet'
14
14
 
15
+ require 'flapjack/data/condition'
16
+
15
17
  module Flapjack
16
18
 
17
19
  class Coordinator
18
20
 
19
- def initialize(config)
20
- @config = config
21
- @redis_options = config.for_redis
22
- @pikelets = []
23
-
24
- @received_signals = []
25
-
26
- @logger = Flapjack::Logger.new("flapjack-coordinator", @config.all['logger'])
27
- end
21
+ # states: :starting, :running, :reloading, :stopped
28
22
 
29
- def start(options = {})
30
- @boot_time = Time.now
23
+ def initialize(config)
24
+ Thread.abort_on_exception = true
31
25
 
32
- EM.synchrony do
33
- setup_signals if options[:signals]
26
+ ActiveSupport.use_standard_json_time_format = true
27
+ ActiveSupport.time_precision = 0
34
28
 
35
- redis = Flapjack::RedisPool.new(:config => @redis_options, :size => 1, :logger => @logger)
36
- ['entity', 'check'].each do |type|
37
- discovered = redis.keys("#{type}_tag:*")
38
- redis.sadd("known_tags:#{type}_tag", discovered) unless discovered.empty?
39
- end
29
+ @exit_value = nil
40
30
 
41
- begin
42
- add_pikelets(pikelets(@config.all))
43
- loop do
44
- while sig = @received_signals.shift do
45
- case sig
46
- when 'INT', 'TERM'
47
- @exit_value = Signal.list[sig] + 128
48
- raise Interrupt
49
- when 'HUP'
50
- reload
51
- end
52
- end
53
- EM::Synchrony.sleep 0.25
54
- end
55
- rescue Exception => e
56
- unless e.is_a?(Interrupt)
57
- trace = e.backtrace.join("\n")
58
- @logger.fatal "#{e.class.name}\n#{e.message}\n#{trace}"
59
- @exit_value = 1
60
- end
61
- remove_pikelets(@pikelets)
62
- EM.stop
63
- end
64
- end
31
+ @config = config
32
+ @pikelets = []
65
33
 
66
- Syslog.close if Syslog.opened?
34
+ @received_signals = []
67
35
 
68
- @exit_value
36
+ @state = :starting
37
+ @monitor = Monitor.new
38
+ @monitor_cond = @monitor.new_cond
39
+
40
+ # needs to be done per-thread
41
+ cfg = @config.all
42
+ Flapjack.configure_log('flapjack-coordinator', cfg.nil? ? {} : cfg['logger'])
43
+
44
+ @reload = proc {
45
+ @monitor.synchronize {
46
+ @monitor_cond.wait_until { :running.eql?(@state) }
47
+ @state = :reloading
48
+ @monitor_cond.signal
49
+ }
50
+ }
51
+
52
+ @shutdown = proc { |exit_val|
53
+ @monitor.synchronize {
54
+ @monitor_cond.wait_until { :running.eql?(@state) }
55
+ @state = :stopping
56
+ @exit_value = exit_val
57
+ @monitor_cond.signal
58
+ }
59
+ }
69
60
  end
70
61
 
71
- private
72
-
73
- def reload
74
- prev_pikelet_cfg = pikelets(@config.all)
75
-
76
- removed = []
77
- added = []
78
- ask_running = []
62
+ def start(opts = {})
63
+ # we can't block on the main thread, as signals interrupt that
64
+ Thread.new do
65
+ # needs to be done per-thread
66
+ cfg = @config.all
67
+ Flapjack.configure_log('flapjack-coordinator', cfg.nil? ? {} : cfg['logger'])
79
68
 
80
- cfg_filename = @config.filename
81
- @config = Flapjack::Configuration.new
82
- @config.load(cfg_filename)
69
+ @boot_time = Time.now
83
70
 
84
- enabled_pikelet_cfg = pikelets(@config.all)
71
+ Flapjack::RedisProxy.config = @config.for_redis
85
72
 
86
- (prev_pikelet_cfg.keys + enabled_pikelet_cfg.keys).each do |type|
73
+ pikelet_defs = pikelet_definitions(cfg)
74
+ return if pikelet_defs.empty?
87
75
 
88
- if prev_pikelet_cfg.keys.include?(type)
89
- if enabled_pikelet_cfg.keys.include?(type)
90
- ask_running << type
91
- else
92
- removed << type
93
- end
94
- elsif enabled_pikelet_cfg.keys.include?(type)
95
- added << type
76
+ create_pikelets(pikelet_defs).each do |pik|
77
+ @pikelets << pik
96
78
  end
97
79
 
98
- end
99
-
100
- @pikelets.select {|pik| ask_running.include?(pik.type) }.each do |pik|
101
- # for sections previously there and still there, ask them
102
- # to make the config change; they will if they can, or will signal
103
- # restart is needed if not
104
-
105
- # reload() returns trinary value here; true means the change was made, false
106
- # means the pikelet needs to be restarted, nil means no change
107
- # was required
108
- next unless pik.reload(enabled_pikelet_cfg[pik.type]).is_a?(FalseClass)
109
- removed << pik.type
110
- added << pik.type
111
- end
112
-
113
- removed_pikelets = @pikelets.select {|pik| removed.include?(pik.type) }
80
+ @pikelets.each do |pik|
81
+ pik.start
82
+ end
114
83
 
115
- remove_pikelets(removed_pikelets)
84
+ setup_signals if opts[:signals]
85
+
86
+ # block this thread until 'stop' has been called, and
87
+ # all pikelets have been stopped
88
+ @monitor.synchronize {
89
+ @state = :running
90
+ @monitor_cond.wait_until { !(:running.eql?(@state)) }
91
+ case @state
92
+ when :reloading
93
+ reload
94
+ @state = :running
95
+ @monitor_cond.signal
96
+ when :stopping
97
+ @pikelets.map(&:stop)
98
+ @pikelets.clear
99
+ @state = :stopped
100
+ @monitor_cond.signal
101
+ end
102
+ }
116
103
 
117
- # is there a nicer way to only keep the parts of the hash with matching keys?
118
- added_pikelets = enabled_pikelet_cfg.select {|k, v| added.include?(k) }
104
+ end.join
119
105
 
120
- add_pikelets(added_pikelets)
106
+ @exit_value
121
107
  end
122
108
 
109
+ private
110
+
123
111
  # the global nature of this seems at odds with it calling stop
124
112
  # within a single coordinator instance. Coordinator is essentially
125
113
  # a singleton anyway...
126
114
  def setup_signals
127
- Kernel.trap('INT') { @received_signals << 'INT' unless @received_signals.include?('INT') }
128
- Kernel.trap('TERM') { @received_signals << 'TERM' unless @received_signals.include?('TERM') }
115
+ Kernel.trap('INT') { Thread.new { @shutdown.call(Signal.list['INT']) }.join }
116
+ Kernel.trap('TERM') { Thread.new { @shutdown.call(Signal.list['TERM']) }.join }
129
117
  unless RbConfig::CONFIG['host_os'] =~ /mswin|windows|cygwin/i
130
- Kernel.trap('HUP') { @received_signals << 'HUP' unless @received_signals.include?('HUP') }
131
- end
132
- end
133
-
134
- # passed a hash with {PIKELET_TYPE => PIKELET_CFG, ...}
135
- def add_pikelets(pikelets_data = {})
136
- pikelets_data.each_pair do |type, cfg|
137
- next unless pikelet = Flapjack::Pikelet.create(type,
138
- :config => cfg, :redis_config => @redis_options,
139
- :boot_time => @boot_time)
140
-
141
- @pikelets << pikelet
142
- pikelet.start
143
- end
144
- end
145
-
146
- def remove_pikelets(piks, opts = {})
147
- piks.map(&:stop)
148
-
149
- loop do
150
- # only prints state changes, otherwise pikelets not closing promptly can
151
- # cause everything else to be spammy
152
- piks.each do |pik|
153
- old_status = pik.status
154
- pik.update_status
155
- status = pik.status
156
- next if old_status.eql?(status)
157
- @logger.info "#{pik.type}: #{old_status} -> #{status}"
158
- end
159
-
160
- if piks.any? {|p| p.status == 'stopping' }
161
- EM::Synchrony.sleep 0.25
162
- else
163
- @pikelets -= piks
164
- break
165
- end
118
+ Kernel.trap('HUP') { Thread.new { @reload.call }.join }
166
119
  end
167
120
  end
168
121
 
169
- def pikelets(config_env)
122
+ def pikelet_definitions(config_env)
170
123
  config = {}
171
124
  return config unless config_env
172
125
 
@@ -197,6 +150,62 @@ module Flapjack
197
150
  } )
198
151
  end
199
152
 
153
+ # passed a hash with {PIKELET_TYPE => PIKELET_CFG, ...}
154
+ # returns unstarted pikelet instances.
155
+ def create_pikelets(pikelets_data = {})
156
+ pikelets_data.inject([]) do |memo, (type, cfg)|
157
+ pikelets = Flapjack::Pikelet.create(type, @shutdown, :config => cfg,
158
+ :boot_time => @boot_time)
159
+ memo += pikelets
160
+ memo
161
+ end
162
+ end
163
+
164
+ # NB: global config options (e.g. daemonize, pidfile,
165
+ # logfile, redis options) won't be checked on reload.
166
+ # should we do a full restart if some of these change?
167
+ def reload
168
+ # TODO refactor cfg load and key retrieval, consolidate with initial load
169
+ prev_pikelet_cfg = pikelet_definitions(@config.all)
170
+
171
+ @config.reload
172
+
173
+ current_pikelet_cfg = pikelet_definitions(@config.all)
174
+
175
+ prev_keys = prev_pikelet_cfg.keys
176
+ current_keys = current_pikelet_cfg.keys
177
+
178
+ removed = prev_keys - current_keys
179
+ added = current_keys - prev_keys
180
+ ask_running = current_keys - (added + removed)
181
+
182
+ # for sections previously there and still there, ask them
183
+ # to make the config change; they will if they can, or will signal
184
+ # restart is needed if not
185
+ # reload() returns trinary value here; true means the change was made, false
186
+ # means the pikelet needs to be restarted, nil means no change
187
+ # was required.
188
+ ask_running.each do |ask_key|
189
+ next unless pikelet = @pikelets.detect {|pik| ask_key == pik.type}
190
+
191
+ if pikelet.reload(current_pikelet_cfg[pikelet.type]).is_a?(FalseClass)
192
+ removed << pikelet.type
193
+ added << pikelet.type
194
+ end
195
+ end
196
+
197
+ pikelets_to_remove = @pikelets.select{|pik| removed.include?(pik.type) }
198
+ pikelets_to_remove.map(&:stop)
199
+ @pikelets -= pikelets_to_remove
200
+
201
+ added_defs = current_pikelet_cfg.select {|k, v| added.include?(k) }
202
+
203
+ create_pikelets(added_defs).each do |pik|
204
+ @pikelets << pik
205
+ pik.start
206
+ end
207
+ end
208
+
200
209
  end
201
210
 
202
211
  end
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'securerandom'
4
+
5
+ require 'active_model'
6
+ require 'swagger/blocks'
7
+
8
+ require 'zermelo/records/stub'
9
+
10
+ require 'flapjack/data/extensions/associations'
11
+ require 'flapjack/data/extensions/short_name'
12
+
13
+ require 'flapjack/data/event'
14
+
15
+ module Flapjack
16
+ module Data
17
+ class Acknowledgement
18
+
19
+ include Swagger::Blocks
20
+
21
+ include Zermelo::Records::Stub
22
+ include ActiveModel::Serializers::JSON
23
+ self.include_root_in_json = false
24
+
25
+ include Flapjack::Data::Extensions::Associations
26
+ include Flapjack::Data::Extensions::ShortName
27
+
28
+ define_attributes :duration => :integer,
29
+ :summary => :string
30
+
31
+ attr_accessor :queue
32
+
33
+ def save!
34
+ @id ||= SecureRandom.uuid
35
+ @duration ||= (4 * 60 * 60)
36
+ @saved = true
37
+ end
38
+
39
+ def persisted?
40
+ !@id.nil? && @saved.is_a?(TrueClass)
41
+ end
42
+
43
+ def check=(c)
44
+ raise "Acknowledgement not saved" unless persisted?
45
+ raise "Acknowledgement queue not set" if @queue.nil? || @queue.empty?
46
+ raise "Acknowledgement already sent" if @sent
47
+
48
+ if c.failing && c.enabled
49
+ @checks = [c]
50
+ Flapjack::Data::Event.create_acknowledgements(
51
+ @queue, @checks, :duration => self.duration, :summary => self.summary
52
+ )
53
+ end
54
+
55
+ @sent = true
56
+ end
57
+
58
+ def tag=(t)
59
+ raise "Acknowledgement not saved" unless persisted?
60
+ raise "Acknowledgement queue not set" if @queue.nil? || @queue.empty?
61
+ raise "Acknowledgement already sent" if @sent
62
+
63
+ checks = t.checks.intersect(:failing => true, :enabled => true)
64
+
65
+ unless checks.empty?
66
+ @checks = checks.all
67
+ Flapjack::Data::Event.create_acknowledgements(
68
+ @queue, @checks, :duration => self.duration, :summary => self.summary
69
+ )
70
+ end
71
+
72
+ @sent = true
73
+ end
74
+
75
+ swagger_schema :Acknowledgement do
76
+ key :required, [:id, :type]
77
+ property :id do
78
+ key :type, :string
79
+ key :format, :uuid
80
+ end
81
+ property :type do
82
+ key :type, :string
83
+ key :enum, [Flapjack::Data::Acknowledgement.short_model_name.singular]
84
+ end
85
+ property :duration do
86
+ key :type, :integer
87
+ end
88
+ property :summary do
89
+ key :type, :string
90
+ end
91
+ property :relationships do
92
+ key :"$ref", :AcknowledgementLinks
93
+ end
94
+ end
95
+
96
+ swagger_schema :AcknowledgementLinks do
97
+ # create (and response) must have one (and only one) of these set
98
+ property :check do
99
+ key :"$ref", :CheckLinkage
100
+ end
101
+ property :tag do
102
+ key :"$ref", :TagLinkage
103
+ end
104
+ end
105
+
106
+ swagger_schema :AcknowledgementCreate do
107
+ key :required, [:type]
108
+ property :id do
109
+ key :type, :string
110
+ key :format, :uuid
111
+ end
112
+ property :type do
113
+ key :type, :string
114
+ key :enum, [Flapjack::Data::Acknowledgement.short_model_name.singular]
115
+ end
116
+ property :duration do
117
+ key :type, :integer
118
+ end
119
+ property :summary do
120
+ key :type, :string
121
+ end
122
+ property :relationships do
123
+ key :"$ref", :AcknowledgementCreateLinks
124
+ end
125
+ end
126
+
127
+ swagger_schema :AcknowledgementCreateLinks do
128
+ # create (and response) must have one (and only one) of these set
129
+ # key :required, [:check, :tag]
130
+ property :check do
131
+ key :"$ref", :data_CheckReference
132
+ end
133
+ property :tag do
134
+ key :"$ref", :data_TagReference
135
+ end
136
+ end
137
+
138
+ def self.swagger_included_classes
139
+ # hack -- hardcoding for now
140
+ []
141
+ end
142
+
143
+ def self.jsonapi_methods
144
+ @jsonapi_methods ||= {
145
+ :post => Flapjack::Gateways::JSONAPI::Data::MethodDescriptor.new(
146
+ :attributes => [:duration, :summary],
147
+ :descriptions => {
148
+ :singular => "Acknowledge a check, or acknowledge all checks linked to a tag.",
149
+ :multiple => "Acknowledge multiple checks, or checks linked to different tags."
150
+ }
151
+ )
152
+ }
153
+ end
154
+
155
+ def self.jsonapi_associations
156
+ unless instance_variable_defined?('@jsonapi_associations')
157
+ @jsonapi_associations = {
158
+ :check => Flapjack::Gateways::JSONAPI::Data::JoinDescriptor.new(
159
+ :post => true,
160
+ :number => :singular, :link => false, :includable => false,
161
+ :type => 'check',
162
+ :klass => Flapjack::Data::Check
163
+ ),
164
+ :tag => Flapjack::Gateways::JSONAPI::Data::JoinDescriptor.new(
165
+ :post => true,
166
+ :number => :singular, :link => false, :includable => false,
167
+ :type => 'tag',
168
+ :klass => Flapjack::Data::Tag
169
+ )
170
+ }
171
+ populate_association_data(@jsonapi_associations)
172
+ end
173
+ @jsonapi_associations
174
+ end
175
+ end
176
+ end
177
+ end