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
@@ -7,11 +7,20 @@ module Flapjack
7
7
  class UnscheduledMaintenance
8
8
  include Base
9
9
 
10
- def block?(event, entity_check, previous_state)
11
- result = entity_check.in_unscheduled_maintenance? && !event.acknowledgement?
12
- @logger.debug("Filter: Unscheduled Maintenance: #{result ? "block" : "pass"}")
10
+ def block?(check, opts = {})
11
+ new_state = opts[:new_state]
12
+
13
+ result = check.in_unscheduled_maintenance? &&
14
+ !('acknowledgement'.eql?(new_state.action) ||
15
+ Flapjack::Data::Condition.healthy?(new_state.condition))
16
+
17
+ Flapjack.logger.debug {
18
+ "Filter: Unscheduled Maintenance: #{result ? "block" : "pass"}"
19
+ }
20
+
13
21
  result
14
22
  end
23
+
15
24
  end
16
25
  end
17
26
  end
@@ -1,13 +1,18 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'em-synchrony'
4
- require 'em-synchrony/em-http'
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'uri/https'
6
+
5
7
  require 'active_support/inflector'
6
8
 
7
- require 'flapjack/redis_pool'
9
+ require 'flapjack/redis_proxy'
10
+ require 'flapjack/record_queue'
11
+ require 'flapjack/utility'
12
+ require 'flapjack/exceptions'
8
13
 
9
14
  require 'flapjack/data/alert'
10
- require 'flapjack/utility'
15
+ require 'flapjack/data/check'
11
16
 
12
17
  module Flapjack
13
18
  module Gateways
@@ -15,46 +20,49 @@ module Flapjack
15
20
 
16
21
  SNS_DEFAULT_REGION_NAME = 'us-east-1'
17
22
 
23
+ attr_accessor :sent
24
+
18
25
  include Flapjack::Utility
19
26
 
20
27
  def initialize(opts = {})
28
+ @lock = opts[:lock]
29
+
21
30
  @config = opts[:config]
22
- @logger = opts[:logger]
23
- @redis_config = opts[:redis_config] || {}
24
- @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 1, :logger => @logger)
25
31
 
26
- @logger.info("starting")
27
- @logger.debug("new aws_sns gateway pikelet with the following options: #{@config.inspect}")
32
+ # TODO support for config reloading
33
+ @queue = Flapjack::RecordQueue.new(@config['queue'] || 'sns_notifications',
34
+ Flapjack::Data::Alert)
28
35
 
29
36
  @sent = 0
30
- end
31
-
32
- def stop
33
- @logger.info("stopping")
34
- @should_quit = true
35
37
 
36
- redis_uri = @redis_config[:path] ||
37
- "redis://#{@redis_config[:host] || '127.0.0.1'}:#{@redis_config[:port] || '6379'}/#{@redis_config[:db] || '0'}"
38
- shutdown_redis = EM::Hiredis.connect(redis_uri)
39
- shutdown_redis.rpush(@config['queue'], Flapjack.dump_json('notification_type' => 'shutdown'))
38
+ Flapjack.logger.debug("new sns gateway pikelet with the following options: #{@config.inspect}")
40
39
  end
41
40
 
42
41
  def start
43
- queue = @config['queue']
44
-
45
- until @should_quit
46
- begin
47
- @logger.debug("aws_sns gateway is going into blpop mode on #{queue}")
48
- alert = Flapjack::Data::Alert.next(queue, :redis => @redis, :logger => @logger)
49
- deliver(alert) unless alert.nil?
50
- rescue => e
51
- @logger.error "Error generating or dispatching AWS SNS message: #{e.class}: #{e.message}\n" +
52
- e.backtrace.join("\n")
42
+ begin
43
+ Zermelo.redis = Flapjack.redis
44
+
45
+ loop do
46
+ @lock.synchronize do
47
+ @queue.foreach {|alert| handle_alert(alert) }
48
+ end
49
+
50
+ @queue.wait
53
51
  end
52
+ ensure
53
+ Flapjack.redis.quit
54
54
  end
55
55
  end
56
56
 
57
- def deliver(alert)
57
+ def stop_type
58
+ :exception
59
+ end
60
+
61
+ private
62
+
63
+ def handle_alert(alert)
64
+ Flapjack.logger.debug "Received a notification: #{alert.inspect}"
65
+
58
66
  region_name = @config["region_name"] || SNS_DEFAULT_REGION_NAME
59
67
  hostname = "sns.#{region_name}.amazonaws.com"
60
68
  endpoint = "http://#{hostname}/"
@@ -62,8 +70,8 @@ module Flapjack
62
70
  secret_key = @config["secret_key"]
63
71
  timestamp = Time.at(alert.time).utc.strftime('%Y-%m-%dT%H:%M:%SZ')
64
72
 
65
- address = alert.address
66
- notification_id = alert.notification_id
73
+ address = alert.medium.address
74
+ notification_id = alert.id
67
75
  message_type = alert.rollup ? 'rollup' : 'alert'
68
76
 
69
77
  aws_sns_subject_template_erb, aws_sns_subject_template =
@@ -75,6 +83,7 @@ module Flapjack
75
83
  File.join(File.dirname(__FILE__), 'aws_sns'))
76
84
 
77
85
  @alert = alert
86
+ @check = alert.check
78
87
  bnd = binding
79
88
 
80
89
  begin
@@ -84,13 +93,13 @@ module Flapjack
84
93
  erb_to_be_executed = aws_sns_template
85
94
  message = aws_sns_template_erb.result(bnd).chomp
86
95
  rescue => e
87
- @logger.error "Error while executing the ERB for an AWS SNS message: " +
96
+ Flapjack.logger.error "Error while executing the ERB for an AWS SNS message: " +
88
97
  "ERB being executed: #{erb_to_be_executed}"
89
98
  raise
90
99
  end
91
100
 
92
101
  if @config.nil? || (@config.respond_to?(:empty?) && @config.empty?)
93
- @logger.error "AWS SNS config is missing"
102
+ Flapjack.logger.error "AWS SNS config is missing"
94
103
  return
95
104
  end
96
105
 
@@ -106,7 +115,7 @@ module Flapjack
106
115
  end
107
116
 
108
117
  unless errors.empty?
109
- errors.each {|err| @logger.error err }
118
+ errors.each {|err| Flapjack.logger.error err }
110
119
  return
111
120
  end
112
121
 
@@ -120,27 +129,35 @@ module Flapjack
120
129
  'Timestamp' => timestamp,
121
130
  'AWSAccessKeyId' => access_key.upcase}
122
131
 
123
- string_to_sign = self.class.string_to_sign('POST', hostname, "/", query)
132
+ # TODO ensure we're not getting a cached response from a proxy or similar,
133
+ # use appropriate headers etc.
134
+ string_sign = self.class.string_to_sign('POST', hostname, "/", query)
135
+
136
+ query['Signature'] = self.class.get_signature(secret_key, string_sign)
124
137
 
125
- query['Signature'] = self.class.get_signature(secret_key, string_to_sign)
138
+ req = Net::HTTP::Post.new(endpoint)
139
+ req.set_form_data(query)
126
140
 
127
- http = EM::HttpRequest.new(endpoint).post(:query => query)
141
+ http_response = Net::HTTP.start(hostname) do |http|
142
+ http.request(req)
143
+ end
144
+
145
+ Flapjack.logger.debug "server response: #{http_response.inspect}"
128
146
 
129
- @logger.debug "server response: #{http.response}"
147
+ status = http_response.code
130
148
 
131
- status = (http.nil? || http.response_header.nil?) ? nil : http.response_header.status
132
- if (status >= 200) && (status <= 206)
149
+ if (status.to_i >= 200) && (status.to_i <= 206)
133
150
  @sent += 1
134
- alert.record_send_success!
135
- @logger.debug "Sent notification via SNS, response status is #{status}, " +
151
+ Flapjack.logger.debug "Sent notification via SNS, response status is #{status}, " +
136
152
  "notification_id: #{notification_id}"
137
153
  else
138
- @logger.error "Failed to send notification via SNS, response status is #{status}, " +
154
+ Flapjack.logger.error "Failed to send notification via SNS, response status is #{status}, " +
139
155
  "notification_id: #{notification_id}"
140
156
  end
157
+
141
158
  rescue => e
142
- @logger.error "Error generating or delivering notification to #{address}: #{e.class}: #{e.message}"
143
- @logger.error e.backtrace.join("\n")
159
+ Flapjack.logger.error "Error generating or delivering notification to #{address}: #{e.class}: #{e.message}"
160
+ Flapjack.logger.error e.backtrace.join("\n")
144
161
  raise
145
162
  end
146
163
 
@@ -151,10 +168,10 @@ module Flapjack
151
168
  end
152
169
 
153
170
  def self.string_to_sign(method, host, uri, query)
154
- @safe_re ||= Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
155
-
156
171
  encoded_query = query.keys.sort.collect {|key|
157
- "#{URI.escape(key, @safe_re)}=#{URI.escape(query[key].to_s, @safe_re)}"
172
+ k = URI.encode_www_form_component(key)
173
+ v = URI.encode_www_form_component(query[key].to_s)
174
+ "#{k}=#{v}"
158
175
  }.join("&")
159
176
 
160
177
  [method.upcase,
@@ -167,4 +184,3 @@ module Flapjack
167
184
  end
168
185
  end
169
186
  end
170
-
@@ -1,6 +1,6 @@
1
1
  <% summary = @alert.summary -%>
2
- <%= @alert.type_sentence_case %>: '<%= @alert.check %>' on <%= @alert.entity -%>
3
- <% unless ['acknowledgement', 'test'].include?(@alert.notification_type) -%>
2
+ <%= @alert.type_sentence_case %>: <%= "'#{@check.name}'" -%>
3
+ <% unless ['acknowledgement', 'test'].include?(@alert.type) -%>
4
4
  is <%= @alert.state_title_case -%>
5
5
  <% end -%>
6
6
  at <%= Time.at(@alert.time).strftime('%-d %b %H:%M') %><%= (summary.nil? || summary.empty?) ? '' : ", #{summary}" -%>
@@ -1,4 +1,4 @@
1
- <%= @alert.type_sentence_case %>: '<%= @alert.check %>' on <%= @alert.entity -%>
1
+ <%= @alert.type_sentence_case %>: '<%= @check.name %>' -%>
2
2
  <% unless ['acknowledgement', 'test'].include?(@alert.notification_type) -%>
3
3
  is <%= @alert.state_title_case -%>
4
- <% end -%>
4
+ <% end -%>
@@ -1 +1 @@
1
- <%= @alert.type_sentence_case %>: <%= @alert.rollup_states_summary -%>
1
+ <%= @alert.type_sentence_case %>: <%= @alert.rollup_states_summary -%>
@@ -6,14 +6,14 @@ require 'socket'
6
6
  require 'chronic_duration'
7
7
  require 'active_support/inflector'
8
8
 
9
- require 'em-synchrony'
10
- require 'em/protocols/smtpclient'
11
-
12
- require 'flapjack/redis_pool'
9
+ require 'flapjack/redis_proxy'
10
+ require 'flapjack/record_queue'
13
11
  require 'flapjack/utility'
12
+ require 'flapjack/exceptions'
14
13
 
15
- require 'flapjack/data/entity_check'
16
14
  require 'flapjack/data/alert'
15
+ require 'flapjack/data/check'
16
+ require 'flapjack/data/contact'
17
17
 
18
18
  module Flapjack
19
19
  module Gateways
@@ -22,112 +22,130 @@ module Flapjack
22
22
 
23
23
  include Flapjack::Utility
24
24
 
25
+ attr_accessor :sent
26
+
25
27
  def initialize(opts = {})
28
+ @lock = opts[:lock]
26
29
  @config = opts[:config]
27
- @logger = opts[:logger]
28
- @redis_config = opts[:redis_config] || {}
29
- @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 1, :logger => @logger)
30
30
 
31
- @logger.info("starting")
32
- @logger.debug("new email gateway pikelet with the following options: #{@config.inspect}")
33
- @smtp_config = @config.delete('smtp_config')
34
- @sent = 0
35
- @fqdn = `/bin/hostname -f`.chomp
36
- end
31
+ # TODO support for config reloading
32
+ @queue = Flapjack::RecordQueue.new(@config['queue'] || 'email_notifications',
33
+ Flapjack::Data::Alert)
37
34
 
38
- def stop
39
- @logger.info("stopping")
40
- @should_quit = true
35
+ if @smtp_config = @config['smtp_config']
36
+ @host = @smtp_config['host'] || 'localhost'
37
+ @port = @smtp_config['port'] || 25
41
38
 
42
- redis_uri = @redis_config[:path] ||
43
- "redis://#{@redis_config[:host] || '127.0.0.1'}:#{@redis_config[:port] || '6379'}/#{@redis_config[:db] || '0'}"
44
- shutdown_redis = EM::Hiredis.connect(redis_uri)
45
- shutdown_redis.rpush(@config['queue'], Flapjack.dump_json('notification_type' => 'shutdown'))
39
+ # NB: needs testing
40
+ if @smtp_config['authentication'] && @smtp_config['username'] &&
41
+ @smtp_config['password']
42
+
43
+ @auth = {:authentication => @smtp_config['authentication'],
44
+ :username => @smtp_config['username'],
45
+ :password => @smtp_config['password'],
46
+ :enable_starttls_auto => true
47
+ }
48
+ end
49
+
50
+ else
51
+ @host = 'localhost'
52
+ @port = 25
53
+ end
54
+
55
+ @fqdn = `/bin/hostname -f`.chomp
56
+ @sent = 0
46
57
  end
47
58
 
48
59
  def start
49
- queue = @config['queue']
50
-
51
- until @should_quit
52
- begin
53
- @logger.debug("email gateway is going into blpop mode on #{queue}")
54
- alert = Flapjack::Data::Alert.next(queue, :redis => @redis, :logger => @logger)
55
- deliver(alert) unless alert.nil?
56
- rescue => e
57
- @logger.error "Error generating or dispatching email message: #{e.class}: #{e.message}\n" +
58
- e.backtrace.join("\n")
60
+ Flapjack.logger.debug("new email gateway pikelet with the following options: #{@config.inspect}")
61
+
62
+ begin
63
+ Zermelo.redis = Flapjack.redis
64
+
65
+ loop do
66
+ @lock.synchronize do
67
+ @queue.foreach {|alert| handle_alert(alert) }
68
+ end
69
+
70
+ @queue.wait
59
71
  end
72
+ ensure
73
+ Flapjack.redis.quit
60
74
  end
61
75
  end
62
76
 
63
- def deliver(alert)
64
- host = @smtp_config ? @smtp_config['host'] : nil
65
- port = @smtp_config ? @smtp_config['port'] : nil
66
- starttls = @smtp_config ? !! @smtp_config['starttls'] : nil
67
- m_from = @smtp_config ? @smtp_config['from'] : "flapjack@#{@fqdn}"
68
- m_reply_to = @smtp_config ? ( @smtp_config['reply_to'] ||= m_from ) : "flapjack@#{@fqdn}"
77
+ def stop_type
78
+ :exception
79
+ end
80
+
81
+ private
82
+
83
+ def safe_address(addr)
84
+ return "flapjack@#{@fqdn}" if addr.nil? || addr.empty?
85
+ safe_addr = addr.clone
86
+ while safe_addr =~ /(<|>)/
87
+ safe_addr.sub!(/^.*</, '').sub!(/>.*$/, '')
88
+ end
89
+
90
+ safe_addr
91
+ end
92
+
93
+ def handle_alert(alert)
94
+ Flapjack.logger.debug "Woo, got an alert to send out: #{alert.inspect}"
69
95
  if @smtp_config
96
+ host = @smtp_config['host']
97
+ port = @smtp_config['port']
98
+ starttls = !!@smtp_config['starttls']
99
+
100
+ m_from = safe_address(@smtp_config['from'])
101
+ m_reply_to = @smtp_config['reply_to'] || @smtp_config['from']
102
+
70
103
  if auth_config = @smtp_config['auth']
71
104
  auth = {}
72
- auth[:type] = auth_config['type'].to_sym || :plain
105
+ auth[:type] = auth_config['type'].to_sym || :plain
73
106
  auth[:username] = auth_config['username']
74
107
  auth[:password] = auth_config['password']
75
108
  end
109
+ else
110
+ host = nil
111
+ port = nil
112
+ starttls = nil
113
+ m_reply_to = m_from = "flapjack@#{@fqdn}"
76
114
  end
77
115
 
78
- @logger.debug("flapjack_mailer: set from to #{m_from}")
79
-
80
- mail = prepare_email(:from => m_from,
81
- :reply_to => m_reply_to,
82
- :to => alert.address,
83
- :message_id => "<#{alert.notification_id}@#{@fqdn}>",
84
- :alert => alert)
85
-
86
- smtp_from = m_from.clone
87
- while smtp_from =~ /(<|>)/
88
- smtp_from.sub!(/^.*</, '')
89
- smtp_from.sub!(/>.*$/, '')
90
- end
91
-
92
- smtp_args = {:from => smtp_from,
93
- :to => alert.address,
94
- :content => "#{mail.to_s}\r\n.\r\n",
95
- :domain => @fqdn,
96
- :host => host || 'localhost',
97
- :port => port || 25,
98
- :starttls => starttls}
99
- smtp_args.merge!(:auth => auth) if auth
100
-
101
- email = EM::P::SmtpClient.send(smtp_args)
116
+ Flapjack.logger.debug("flapjack_mailer: set from to #{m_from}")
102
117
 
103
- response = EM::Synchrony.sync(email)
118
+ mail = prepare_email(:from => m_from,
119
+ :reply_to => m_reply_to,
120
+ :to => alert.medium.address,
121
+ :message_id => "<#{alert.id}@#{@fqdn}>",
122
+ :alert => alert)
104
123
 
105
- # http://tools.ietf.org/html/rfc821#page-36 SMTP response codes
106
- if response && response.respond_to?(:code) &&
107
- ((response.code == 250) || (response.code == 251))
108
- alert.record_send_success!
109
- @sent += 1
110
- else
111
- @logger.error "Email sending failed"
124
+ # TODO a cleaner way to not step on test delivery settings
125
+ # (don't want to stub in Cucumber)
126
+ unless defined?(FLAPJACK_ENV) && 'test'.eql?(FLAPJACK_ENV)
127
+ mail.delivery_method(:smtp, {:address => @host,
128
+ :port => @port}.merge(@auth || {}))
112
129
  end
113
130
 
114
- @logger.debug "Email response: #{response.inspect}"
131
+ # any exceptions will be propagated through to main pikelet handler
132
+ mail.deliver
115
133
 
134
+ Flapjack.logger.info "Email sending succeeded"
135
+ @sent += 1
116
136
  rescue => e
117
- @logger.error "Error generating or delivering email to #{alert.address}: #{e.class}: #{e.message}"
118
- @logger.error e.backtrace.join("\n")
137
+ Flapjack.logger.error "Error generating or delivering email to #{alert.medium.address}: #{e.class}: #{e.message}"
138
+ Flapjack.logger.error e.backtrace.join("\n")
119
139
  raise
120
140
  end
121
141
 
122
- private
123
-
124
142
  # returns a Mail object
125
143
  def prepare_email(opts = {})
126
- from = opts[:from]
127
- reply_to = opts[:reply_to]
128
- to = opts[:to]
144
+ from = opts[:from]
145
+ to = opts[:to]
146
+ reply_to = opts[:reply_to]
129
147
  message_id = opts[:message_id]
130
- alert = opts[:alert]
148
+ alert = opts[:alert]
131
149
 
132
150
  message_type = alert.rollup ? 'rollup' : 'alert'
133
151
 
@@ -143,8 +161,8 @@ module Flapjack
143
161
  load_template(@config['templates'], message_type,
144
162
  'html', File.join(File.dirname(__FILE__), 'email'))
145
163
 
146
- @alert = alert
147
- bnd = binding
164
+ @alert = alert
165
+ bnd = binding
148
166
 
149
167
  # do some intelligence gathering in case an ERB execution blows up
150
168
  begin
@@ -156,19 +174,19 @@ module Flapjack
156
174
 
157
175
  erb_to_be_executed = html_template
158
176
  body_html = html_template_erb.result(bnd)
159
- rescue => e
160
- @logger.error "Error while executing ERBs for an email: " +
177
+ rescue
178
+ Flapjack.logger.error "Error while executing ERBs for an email: " +
161
179
  "ERB being executed: #{erb_to_be_executed}"
162
180
  raise
163
181
  end
164
182
 
165
- @logger.debug("preparing email to: #{to}, subject: #{subject}, message-id: #{message_id}")
183
+ Flapjack.logger.debug("preparing email to: #{to}, subject: #{subject}, message-id: #{message_id}")
166
184
 
167
- mail = Mail.new do
168
- from from
169
- to to
170
- subject subject
171
- reply_to reply_to
185
+ Mail.new do
186
+ from from
187
+ to to
188
+ subject subject
189
+ reply_to reply_to
172
190
  message_id message_id
173
191
 
174
192
  text_part do
@@ -180,7 +198,6 @@ module Flapjack
180
198
  body body_html
181
199
  end
182
200
  end
183
-
184
201
  end
185
202
  end
186
203
  end