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
@@ -5,23 +5,24 @@ require 'rack'
5
5
  module Flapjack
6
6
  module Gateways
7
7
  class JSONAPI < Sinatra::Base
8
- module Rack
8
+ module Middleware
9
9
  class JsonParamsParser < Struct.new(:app)
10
10
  def call(env)
11
11
  t = type(env)
12
- if env['rack.input'] && !input_parsed?(env) && type_match?(t)
12
+ if ['POST', 'PATCH', 'DELETE'].include?(env["REQUEST_METHOD"]) &&
13
+ env['rack.input'] && !input_parsed?(env) && type_match?(t)
14
+
13
15
  env['rack.request.form_input'] = env['rack.input']
14
16
  json_data = env['rack.input'].read
15
17
  env['rack.input'].rewind
16
18
  data = json_data.empty? ? {} : Flapjack.load_json(json_data)
17
- env['rack.request.form_hash'] = data.empty? ? {} :
18
- (('application/json-patch+json'.eql?(t)) ? {'ops' => data} : data)
19
+ env['rack.request.form_hash'] = data
19
20
  end
20
21
  app.call(env)
21
22
  end
22
23
 
23
24
  def input_parsed? env
24
- env['rack.request.form_input'].eql? env['rack.input']
25
+ env['rack.request.form_input'].eql?(env['rack.input'])
25
26
  end
26
27
 
27
28
  def type(env)
@@ -30,7 +31,7 @@ module Flapjack
30
31
  end
31
32
 
32
33
  def type_match?(t)
33
- Flapjack::Gateways::JSONAPI::JSON_REQUEST_MIME_TYPES.include?(t)
34
+ Flapjack::Gateways::JSONAPI::JSONAPI_MEDIA_TYPE.eql?(t)
34
35
  end
35
36
  end
36
37
  end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rack'
4
+
5
+ module Flapjack
6
+ module Gateways
7
+ class JSONAPI < Sinatra::Base
8
+ module Middleware
9
+ class RequestTimestamp < Struct.new(:app)
10
+ def call(env)
11
+ env['request_timestamp'] = Time.now
12
+ app.call(env)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,240 +1,292 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'net/http'
3
4
  require 'socket'
4
- require 'eventmachine'
5
- require 'em-synchrony'
6
- require 'blather/client/client'
5
+ require 'uri'
6
+ require 'uri/https'
7
7
 
8
+ require 'xmpp4r'
9
+ require 'xmpp4r/muc/helper/simplemucclient'
10
+
11
+ require 'flapjack/exceptions'
8
12
  require 'flapjack/utility'
9
13
 
10
14
  module Flapjack
11
15
 
12
16
  module Gateways
13
17
 
14
- class Oobetet < Blather::Client
15
- include Flapjack::Utility
18
+ module Oobetet
16
19
 
17
- log = ::Logger.new(STDOUT)
18
- log.level = ::Logger::INFO
19
- Blather.logger = log
20
+ class Notifier
20
21
 
21
- def initialize(opts = {})
22
- @config = opts[:config]
23
- @logger = opts[:logger]
24
- super()
25
- end
22
+ attr_accessor :siblings
26
23
 
27
- def stop
28
- @should_quit = true
29
- end
24
+ def initialize(options = {})
25
+ @lock = options[:lock]
26
+ @config = options[:config]
30
27
 
31
- def setup
32
- @hostname = Socket.gethostname
33
- @flapjacktest_jid = Blather::JID.new((@config['jabberid'] || 'flapjacktest') + "/#{@hostname}:#{Process.pid}")
28
+ @hostname = Socket.gethostname
34
29
 
35
- super(@flapjacktest_jid, @config['password'], @config['server'], @config['port'].to_i)
30
+ unless @config['watched_check']
31
+ raise RuntimeError, 'Flapjack::Oobetet: watched_check must be defined in the config'
32
+ end
33
+ @check_matcher = '"' + @config['watched_check'] + '"'
36
34
 
37
- @logger.debug("Building jabber connection with jabberid: " +
38
- @flapjacktest_jid.to_s + ", port: " + @config['port'].to_s +
39
- ", server: " + @config['server'].to_s + ", password: " +
40
- @config['password'].to_s)
35
+ @flapjack_ok = true
36
+ @last_alert = nil
37
+ @last_breach = nil
38
+ end
41
39
 
42
- @pagerduty_events_api_url = 'https://events.pagerduty.com/generic/2010-04-15/create_event.json'
40
+ def start
41
+ loop do
42
+ @lock.synchronize do
43
+ check_timers
44
+ end
43
45
 
44
- if !@config['watched_check'] or !@config['watched_entity']
45
- raise RuntimeError, 'Flapjack::Oobetet: watched_check and watched_entity must be defined in the config'
46
+ Kernel.sleep 10
47
+ end
46
48
  end
47
49
 
48
- @check_matcher = '"' + @config['watched_check'] + '" on ' + @config['watched_entity']
49
- @max_latency = @config['max_latency'] || 300
50
- @flapjack_ok = true
51
-
52
- t = Time.now.to_i
53
- @times = { :last_problem => t,
54
- :last_recovery => t,
55
- :last_ack => t,
56
- :last_ack_sent => t }
50
+ def stop_type
51
+ :exception
52
+ end
57
53
 
58
- @last_alert = nil
59
- end
54
+ private
60
55
 
61
- # split out to ease testing
62
- def register_handlers
63
- register_handler :ready do |stanza|
64
- EventMachine::Synchrony.next_tick do
65
- on_ready(stanza)
56
+ def check_timers
57
+ if @siblings
58
+ @time_checker ||= @siblings.detect {|sib| sib.respond_to?(:breach?) }
59
+ @bot ||= @siblings.detect {|sib| sib.respond_to?(:announce) }
66
60
  end
67
- end
68
61
 
69
- register_handler :message, :groupchat? do |stanza|
70
- EventMachine::Synchrony.next_tick do
71
- on_groupchat(stanza)
62
+ t = Time.now
63
+ breach = @time_checker.breach?(t) if @time_checker
64
+
65
+ if @last_breach && !breach
66
+ emit_jabber("Flapjack Self Monitoring is OK")
67
+ emit_pagerduty("Flapjack Self Monitoring is OK", 'resolve')
72
68
  end
73
- end
74
69
 
75
- register_handler :disconnected do |stanza|
76
- ret = true
77
- EventMachine::Synchrony.next_tick do
78
- ret = on_disconnect(stanza)
70
+ @last_breach = breach
71
+ return unless breach
72
+
73
+ Flapjack.logger.error("Self monitoring has detected the following breach: #{breach}")
74
+ summary = "Flapjack Self Monitoring is Critical: #{breach} for #{@check_matcher}, " +
75
+ "from #{@hostname} at #{t}"
76
+
77
+ if @last_alert.nil? || @last_alert < (t.to_i - 55)
78
+
79
+ announced_jabber = emit_jabber(summary)
80
+ announced_pagerduty = emit_pagerduty(summary, 'trigger')
81
+
82
+ @last_alert = t.to_i if announced_jabber || announced_pagerduty
83
+
84
+ if @last_alert.nil? || @last_alert < (t.to_i - 55)
85
+ msg = "NOTICE: Self monitoring has detected a failure and is unable to tell " +
86
+ "anyone about it. DON'T PANIC."
87
+ Flapjack.logger.error msg
88
+ end
79
89
  end
80
- ret
81
90
  end
82
- end
83
91
 
92
+ def emit_jabber(summary)
93
+ return if @bot.nil?
94
+ @bot.announce(summary)
95
+ true
96
+ end
84
97
 
85
- # Join the MUC Chat room after connecting.
86
- def on_ready(stanza)
87
- return if @should_quit
88
- @connected_at = Time.now.to_i
89
- @logger.info("Jabber Connected")
90
- if @config['rooms'] && @config['rooms'].length > 0
91
- @config['rooms'].each do |room|
92
- @logger.info("Joining room #{room}")
93
- presence = Blather::Stanza::Presence.new
94
- presence.from = @flapjacktest_jid
95
- presence.to = Blather::JID.new("#{room}/#{@config['alias']}")
96
- presence << "<x xmlns='http://jabber.org/protocol/muc'/>"
97
- write presence
98
- say(room, "flapjack self monitoring (oobetet) started at #{Time.now}, g'day!", :groupchat)
98
+ def emit_pagerduty(summary, event_type = 'trigger')
99
+ return if @config['pagerduty_contact'].nil?
100
+ status, response = send_pagerduty_event(:service_key => @config['pagerduty_contact'],
101
+ :incident_key => "Flapjack Self Monitoring from #{@hostname}",
102
+ :event_type => event_type,
103
+ :description => summary)
104
+ unless '200'.eql?(status)
105
+ Flapjack.logger.error("pagerduty returned #{status} #{response.inspect}")
106
+ return false
99
107
  end
108
+
109
+ Flapjack.logger.debug("successfully sent pagerduty event")
110
+ true
100
111
  end
101
- end
102
112
 
103
- # returning true to prevent the reactor loop from stopping
104
- def on_disconnect(stanza)
105
- return true if @should_quit
106
- @logger.warn("jabbers disconnected! reconnecting in 1 second ...")
107
- EventMachine::Timer.new(1) do
108
- connect # Blather::Client.connect
113
+ # TODO trap Oj JSON errors
114
+ # FIXME common code with the pagerduty gateway, move to shared module
115
+ def send_pagerduty_event(opts = {})
116
+ event = { 'service_key' => opts[:service_key],
117
+ 'incident_key' => opts[:incident_key],
118
+ 'event_type' => opts[:event_type],
119
+ 'description' => opts[:description] }
120
+
121
+ uri = URI::HTTPS.build(:host => 'events.pagerduty.com',
122
+ :path => '/generic/2010-04-15/create_event.json',
123
+ :port => 443)
124
+ http = Net::HTTP.new(uri.host, uri.port)
125
+ http.use_ssl = true
126
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
127
+ request = Net::HTTP::Post.new(uri.request_uri)
128
+ request.body = Flapjack.dump_json(event)
129
+ http_response = http.request(request)
130
+
131
+ response = Flapjack.load_json(http_response.body)
132
+ status = http_response.code
133
+ Flapjack.logger.debug "send_pagerduty_event got a return code of #{status} - #{response.inspect}"
134
+ [status, response]
109
135
  end
110
- true
136
+
111
137
  end
112
138
 
113
- def on_groupchat(stanza)
114
- return if @should_quit
139
+ class TimeChecker
115
140
 
116
- stanza_body = stanza.body
141
+ def initialize(opts = {})
142
+ @lock = opts[:lock]
143
+ @stop_cond = opts[:stop_condition]
144
+ @config = opts[:config]
117
145
 
118
- @logger.debug("groupchat stanza body: #{stanza_body}")
119
- @logger.debug("groupchat message received: #{stanza.inspect}")
146
+ @max_latency = @config['max_latency'] || 300
120
147
 
121
- if (stanza_body =~ /^(?:problem|recovery|acknowledgement)/i) &&
122
- (stanza_body =~ /^(\w+).*#{Regexp.escape(@check_matcher)}/)
148
+ @times = { :last_problem => nil,
149
+ :last_recovery => nil,
150
+ :last_ack => nil,
151
+ :last_ack_sent => nil }
123
152
 
124
- # got something interesting
125
- status = $1.downcase
126
- t = Time.now.to_i
127
- @logger.debug("groupchat found the following state for #{@check_matcher}: #{status}")
153
+ Flapjack.logger.debug("new oobetet pikelet with the following options: #{@config.inspect}")
154
+ end
128
155
 
129
- case status
130
- when 'problem'
131
- @logger.debug("updating @times last_problem")
132
- @times[:last_problem] = t
133
- when 'recovery'
134
- @logger.debug("updating @times last_recovery")
156
+ def start
157
+ @lock.synchronize do
158
+ t = Time.now.to_i
159
+ @times[:last_problem] = t
135
160
  @times[:last_recovery] = t
136
- when 'acknowledgement'
137
- @logger.debug("updating @times last_ack")
138
- @times[:last_ack] = t
161
+ @times[:last_ack] = t
162
+ @times[:last_ack_sent] = t
163
+ @stop_cond.wait_until { @should_quit }
139
164
  end
140
165
  end
141
- @logger.debug("@times: #{@times.inspect}")
142
- end
143
166
 
144
- def check_timers
145
- t = Time.now.to_i
146
- breach = nil
147
- @logger.debug("check_timers: inspecting @times #{@times.inspect}")
148
- case
149
- when @times[:last_problem] < (t - @max_latency)
150
- breach = "haven't seen a test problem notification in the last #{@max_latency} seconds"
151
- when @times[:last_recovery] < (t - @max_latency)
152
- breach = "haven't seen a test recovery notification in the last #{@max_latency} seconds"
167
+ def stop_type
168
+ :signal
169
+ end
170
+
171
+ def receive_status(status, time)
172
+ @lock.synchronize do
173
+ case status
174
+ when 'problem'
175
+ Flapjack.logger.debug("updating @times last_problem")
176
+ @times[:last_problem] = time
177
+ when 'recovery'
178
+ Flapjack.logger.debug("updating @times last_recovery")
179
+ @times[:last_recovery] = time
180
+ when 'acknowledgement'
181
+ Flapjack.logger.debug("updating @times last_ack")
182
+ @times[:last_ack] = time
183
+ end
184
+ Flapjack.logger.debug("@times: #{@times.inspect}")
185
+ end
153
186
  end
154
187
 
155
- unless @flapjack_ok || breach
156
- emit_jabber("Flapjack Self Monitoring is OK")
157
- emit_pagerduty("Flapjack Self Monitoring is OK", 'resolve')
188
+ def breach?(time)
189
+ @lock.synchronize do
190
+ Flapjack.logger.debug("check_timers: inspecting @times #{@times.inspect}")
191
+ if @times[:last_problem] < (time - @max_latency)
192
+ "haven't seen a test problem notification in the last #{@max_latency} seconds"
193
+ elsif @times[:last_recovery] < (time - @max_latency)
194
+ "haven't seen a test recovery notification in the last #{@max_latency} seconds"
195
+ end
196
+ end
158
197
  end
159
198
 
160
- @flapjack_ok = !breach
199
+ end
161
200
 
162
- return unless breach
163
- @logger.error("Self monitoring has detected the following breach: #{breach}")
164
- summary = "Flapjack Self Monitoring is Critical: #{breach} for #{@check_matcher}, "
165
- summary += "from #{@hostname} at #{Time.now}"
201
+ class Bot
166
202
 
167
- if !@last_alert or @last_alert < (t - 55)
203
+ include Flapjack::Utility
168
204
 
169
- emit_jabber(summary)
170
- emit_pagerduty(summary, 'trigger')
205
+ attr_accessor :siblings
171
206
 
172
- if !@last_alert or @last_alert < (t - 55)
173
- msg = "NOTICE: Self monitoring has detected a failure and is unable to tell "
174
- msg += "anyone about it. DON'T PANIC."
175
- @logger.error msg
176
- end
207
+ def initialize(opts = {})
208
+ @lock = opts[:lock]
209
+ @stop_cond = opts[:stop_condition]
210
+ @config = opts[:config]
177
211
 
178
- end
179
- end
212
+ @hostname = Socket.gethostname
180
213
 
181
- def emit_jabber(summary)
182
- if @config['rooms'] && @config['rooms'].length > 0
183
- @config['rooms'].each do |room|
184
- say(room, summary, :groupchat)
214
+ unless @config['watched_check']
215
+ raise RuntimeError, 'Flapjack::Oobetet: watched_check must be defined in the config'
185
216
  end
186
- @last_alert = Time.now.to_i
187
- end
188
- end
217
+ @check_matcher = '"' + @config['watched_check'] + '"'
189
218
 
190
- def emit_pagerduty(summary, event_type = 'trigger')
191
- if @config['pagerduty_contact']
192
- pagerduty_event = { 'service_key' => @config['pagerduty_contact'],
193
- 'incident_key' => "Flapjack Self Monitoring from #{@hostname}",
194
- 'event_type' => event_type,
195
- 'description' => summary }
196
- status, response = send_pagerduty_event(pagerduty_event)
197
- if status == 200
198
- @logger.debug("successfully sent pagerduty event")
199
- @last_alert = Time.now.to_i
200
- else
201
- @logger.error("pagerduty returned #{status} #{response.inspect}")
202
- end
219
+ Flapjack.logger.debug("new oobetet pikelet with the following options: #{@config.inspect}")
203
220
  end
204
- end
205
221
 
206
- def say(to, msg, using = :chat)
207
- @logger.debug("Sending a jabber message to: #{to.to_s}, using: #{using.to_s}, message: #{msg}")
208
- write Blather::Stanza::Message.new(to, msg, using)
209
- end
222
+ def start
223
+ @lock.synchronize do
224
+ @time_checker ||= @siblings && @siblings.detect {|sib| sib.respond_to?(:receive_status) }
210
225
 
211
- def send_pagerduty_event(event)
212
- options = { :body => Flapjack.dump_json(event) }
213
- http = EM::HttpRequest.new(@pagerduty_events_api_url).post(options)
214
- response = Flapjack.load_json(http.response)
215
- status = http.response_header.status
216
- @logger.debug "send_pagerduty_event got a return code of #{status.to_s} - #{response.inspect}"
217
- [status, response]
218
- end
226
+ Flapjack.logger.info("starting")
219
227
 
220
- def start
221
- @logger.debug("New oobetet pikelet with the following options: #{@config.inspect}")
228
+ # ::Jabber::debug = true
222
229
 
223
- keepalive_timer = EM::Synchrony.add_periodic_timer(60) do
224
- @logger.debug("calling keepalive on the jabber connection")
225
- write(' ') if connected?
230
+ jabber_id = @config['jabberid'] || 'flapjack'
231
+
232
+ @flapjack_jid = ::Jabber::JID.new(jabber_id + '/' + @hostname)
233
+ @client = ::Jabber::Client.new(@flapjack_jid)
234
+
235
+ @muc_clients = @config['rooms'].inject({}) do |memo, room|
236
+ muc_client = ::Jabber::MUC::SimpleMUCClient.new(@client)
237
+ memo[room] = muc_client
238
+ memo
239
+ end
240
+
241
+ @client.connect
242
+ @client.auth(@config['password'])
243
+ @client.send(::Jabber::Presence.new.set_type(:available))
244
+
245
+ @muc_clients.each_pair do |room, muc_client|
246
+ muc_client.on_message do |time, nick, text|
247
+ next if nick == jabber_id
248
+
249
+ if @time_checker
250
+ Flapjack.logger.debug("group message received: #{room}, #{text}")
251
+ if (text =~ /^((?i:problem|recovery|acknowledgement)).*#{Regexp.escape(@check_matcher)}/)
252
+ # got something interesting
253
+ status = Regexp.last_match(1).downcase
254
+ Flapjack.logger.debug("found the following state for #{@check_matcher}: #{status}")
255
+ @time_checker.receive_status(status, time.to_i)
256
+ end
257
+ end
258
+ end
259
+
260
+ muc_client.join(room + '/' + @config['alias'])
261
+ muc_client.say("flapjack oobetet gateway started at #{Time.now}, hello!")
262
+ end
263
+
264
+ # block this thread until signalled to quit
265
+ @stop_cond.wait_until { @should_quit }
266
+
267
+ @muc_clients.each_pair do |room, muc_client|
268
+ muc_client.exit if muc_client.active?
269
+ end
270
+
271
+ @client.close
272
+ end
226
273
  end
227
274
 
228
- setup
229
- register_handlers
230
- connect # Blather::Client.connect
275
+ def stop_type
276
+ :signal
277
+ end
231
278
 
232
- until @should_quit
233
- EM::Synchrony.sleep(10)
234
- check_timers
279
+ # TODO buffer if not connected?
280
+ def announce(msg)
281
+ @lock.synchronize do
282
+ unless @muc_clients.empty?
283
+ @muc_clients.each_pair do |room, muc_client|
284
+ muc_client.say(msg)
285
+ end
286
+ end
287
+ end
235
288
  end
236
289
 
237
- keepalive_timer.cancel
238
290
  end
239
291
 
240
292
  end