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,56 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # 'Notification' refers to the template object created when an event occurs,
4
- # from which individual 'Message' objects are created, one for each
5
- # contact+media recipient.
6
-
7
- require 'flapjack/data/contact'
8
-
9
- module Flapjack
10
- module Data
11
- class Message
12
-
13
- attr_reader :medium, :address, :duration, :contact, :rollup
14
-
15
- def self.for_contact(contact, opts = {})
16
- self.new(:contact => contact,
17
- :medium => opts[:medium],
18
- :address => opts[:address],
19
- :duration => opts[:duration],
20
- :rollup => opts[:rollup])
21
- end
22
-
23
- def id
24
- return @id if @id
25
- t = Time.now
26
- # FIXME: consider using a UUID here
27
- # this is planned to be used as part of alert history keys
28
- @id = "#{self.object_id.to_i}-#{t.to_i}.#{t.tv_usec}"
29
- end
30
-
31
- def contents
32
- c = {'media' => medium,
33
- 'address' => address,
34
- 'id' => id,
35
- 'rollup' => rollup,
36
- 'contact_id' => contact.id,
37
- 'contact_first_name' => contact.first_name,
38
- 'contact_last_name' => contact.last_name}
39
- c['duration'] = duration if duration
40
- c
41
- end
42
-
43
- private
44
-
45
- def initialize(opts = {})
46
- @contact = opts[:contact]
47
- @medium = opts[:medium]
48
- @address = opts[:address]
49
- @duration = opts[:duration]
50
- @rollup = opts[:rollup]
51
- end
52
-
53
- end
54
- end
55
- end
56
-
@@ -1,234 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'flapjack/data/contact'
4
- require 'flapjack/data/entity_check'
5
-
6
- require 'flapjack/data/semaphore'
7
-
8
- module Flapjack
9
- module Data
10
- class Migration
11
-
12
- ENTITY_DATA_MIGRATION = 'entity_data_migration'
13
-
14
- # copied from jsonapi/contact_methods.rb, could extract both into separate file
15
- def self.obtain_semaphore(resource, description, options = {})
16
- raise "Redis connection not set" unless redis = options[:redis]
17
-
18
- logger = options[:logger]
19
-
20
- semaphore = nil
21
- strikes = 0
22
- begin
23
- semaphore = Flapjack::Data::Semaphore.new(resource, :redis => redis, :expiry => 300)
24
- rescue Flapjack::Data::Semaphore::ResourceLocked
25
- strikes += 1
26
- if strikes < 10
27
- sleep 2
28
- retry
29
- end
30
- sempahore = nil
31
- end
32
-
33
- if semaphore.nil?
34
- unless logger.nil?
35
- logger.fatal "Could not obtain lock for data migration (#{reason}). Ensure that " +
36
- "no other flapjack processes are running that might be executing " +
37
- "migrations, check logs for any exceptions, manually delete the " +
38
- "'#{resource}' key from your Flapjack Redis " +
39
- "database and try running Flapjack again."
40
- end
41
- raise "Unable to obtain semaphore #{resource}"
42
- end
43
-
44
- semaphore
45
- end
46
-
47
- def self.create_entity_ids_if_required(options = {})
48
- raise "Redis connection not set" unless redis = options[:redis]
49
-
50
- logger = options[:logger]
51
-
52
- return if redis.exists('created_ids_for_old_entities_without_ids')
53
-
54
- semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, 'entity id creation',
55
- :redis => redis, :logger => logger)
56
-
57
- begin
58
- logger.warn "Ensuring all entities have ids ..." unless logger.nil?
59
-
60
- Flapjack::Data::EntityCheck.find_current_names_by_entity(:redis => redis, :logger => logger).keys.each {|entity_name|
61
- entity = Flapjack::Data::Entity.find_by_name(entity_name, :create => true, :redis => redis, :logger => logger)
62
- }
63
-
64
- all_checks = Flapjack::Data::EntityCheck.all(:redis => redis, :logger => logger, :create_entity => true)
65
-
66
- redis.set('created_ids_for_old_entities_without_ids', 'true')
67
- logger.warn "Entity id creation complete."
68
- ensure
69
- semaphore.release
70
- end
71
- end
72
-
73
- def self.migrate_entity_check_data_if_required(options = {})
74
- raise "Redis connection not set" unless redis = options[:redis]
75
-
76
- logger = options[:logger]
77
-
78
- return if redis.exists('all_checks')
79
-
80
- semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, 'entity check data',
81
- :redis => redis, :logger => logger)
82
-
83
- begin
84
- check_names = redis.keys('check:*').map {|c| c.sub(/^check:/, '') } |
85
- Flapjack::Data::EntityCheck.find_current_names(:redis => redis)
86
-
87
- unless check_names.empty?
88
- logger.warn "Upgrading Flapjack's entity/check Redis indexes..." unless logger.nil?
89
-
90
- timestamp = Time.now.to_i
91
-
92
- check_names.each do |ecn|
93
- redis.zadd("all_checks", timestamp, ecn)
94
- entity_name, check = ecn.split(':', 2)
95
- redis.zadd("all_checks:#{entity_name}", timestamp, check)
96
- # not deleting the check hashes, they store useful data
97
- end
98
- logger.warn "Checks indexed." unless logger.nil?
99
- end
100
-
101
- entity_name_keys = redis.keys("entity_id:*")
102
- unless entity_name_keys.empty?
103
- ids = redis.mget(*entity_name_keys)
104
-
105
- entity_name_keys.each do |enk|
106
- enk =~ /^entity_id:(.+)$/; entity_name = $1; entity_id = ids.shift
107
-
108
- redis.hset('all_entity_names_by_id', entity_id, entity_name)
109
- redis.hset('all_entity_ids_by_name', entity_name, entity_id)
110
-
111
- redis.del(enk)
112
- redis.del("entity:#{entity_id}")
113
- end
114
- logger.warn "Entities indexed." unless logger.nil?
115
- end
116
-
117
- logger.warn "Indexing complete." unless logger.nil? || (check_names.empty? && entity_name_keys.empty?)
118
- ensure
119
- semaphore.release
120
- end
121
- end
122
-
123
- def self.clear_orphaned_entity_ids(options = {})
124
- raise "Redis connection not set" unless redis = options[:redis]
125
-
126
- logger = options[:logger]
127
-
128
- semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION,
129
- 'orphaned entity ids', :redis => redis, :logger => logger)
130
-
131
- begin
132
- logger.info "Checking for orphaned entity ids..." unless logger.nil?
133
-
134
- valid_entity_data = redis.hgetall('all_entity_ids_by_name')
135
-
136
- missing_ids = redis.hgetall('all_entity_names_by_id').reject {|e_id, e_name|
137
- valid_entity_data[e_name] == e_id
138
- }
139
-
140
- unless missing_ids.empty?
141
- logger.info "Clearing ids (#{missing_ids.inspect})" unless logger.nil?
142
- redis.hdel('all_entity_names_by_id', missing_ids.keys)
143
- end
144
- ensure
145
- semaphore.release
146
- logger.info "Finished checking for orphaned entity ids." unless logger.nil?
147
- end
148
- end
149
-
150
- def self.refresh_archive_index(options = {})
151
- raise "Redis connection not set" unless redis = options[:redis]
152
- archive_keys = redis.keys('events_archive:*')
153
- if archive_keys.empty?
154
- redis.del('known_events_archive_keys')
155
- return
156
- end
157
-
158
- grouped_keys = archive_keys.group_by do |ak|
159
- (redis.llen(ak) > 0) ? 'add' : 'remove'
160
- end
161
-
162
- {'remove' => :srem, 'add' => :sadd}.each_pair do |k, cmd|
163
- next unless grouped_keys.has_key?(k) && !grouped_keys[k].empty?
164
- redis.send(cmd, 'known_events_archive_keys', grouped_keys[k])
165
- end
166
- end
167
-
168
- def self.purge_expired_archive_index(options = {})
169
- raise "Redis connection not set" unless redis = options[:redis]
170
- return unless redis.exists('known_events_archive_keys')
171
-
172
- redis.smembers('known_events_archive_keys').each do |ak|
173
- redis.srem('known_events_archive_keys', ak) unless redis.exists(ak)
174
- end
175
- end
176
-
177
- def self.correct_notification_rule_contact_linkages(options = {})
178
- raise "Redis connection not set" unless redis = options[:redis]
179
-
180
- logger = options[:logger]
181
-
182
- return if redis.exists('corrected_notification_rule_contact_linkages')
183
-
184
- invalid_notification_rule_keys = redis.keys("notification_rule:*").select {|k|
185
- contact_id = redis.hget(k, 'contact_id')
186
- contact_id.nil? || contact_id.empty?
187
- }.collect {|nrk| nrk.sub(/^notification_rule:/, '') }
188
-
189
- unless invalid_notification_rule_keys.empty?
190
- Flapjack::Data::Contact.all(:redis => redis).each do |contact|
191
- correctable = contact.notification_rule_ids & invalid_notification_rule_keys
192
- next if correctable.empty?
193
- correctable.each {|ck| redis.hset("notification_rule:#{ck}", 'contact_id', contact.id) }
194
- logger.warn "Set contact #{contact.id} for rules #{correctable.join(', ')}" unless logger.nil?
195
- end
196
- end
197
-
198
- redis.set('corrected_notification_rule_contact_linkages', 'true')
199
- end
200
-
201
- def self.validate_scheduled_maintenance_periods(options = {})
202
- raise "Redis connection not set" unless redis = options[:redis]
203
-
204
- logger = options[:logger]
205
-
206
- return if redis.exists('validated_scheduled_maintenance_periods')
207
-
208
- Flapjack::Data::EntityCheck.all(:redis => redis).compact.select {|ec|
209
- ec.in_scheduled_maintenance?
210
- }.each do |check|
211
- check.update_current_scheduled_maintenance(:revalidate => true)
212
- end
213
-
214
- logger.warn "Validated scheduled maintenance period expiry" unless logger.nil?
215
- redis.set('validated_scheduled_maintenance_periods', 'true')
216
- end
217
-
218
- def self.correct_rollup_including_disabled_checks(options = {})
219
- raise "Redis connection not set" unless redis = options[:redis]
220
- logger = options[:logger]
221
- return if redis.exists('corrected_rollup_including_disabled_checks')
222
-
223
- Flapjack::Data::Contact.all(:redis => redis).each do |contact|
224
- contact.media_list.each do |medium|
225
- contact.clean_alerting_checks_for_media(medium)
226
- end
227
- end
228
-
229
- logger.warn "Corrected rollup to no longer include disabled checks" unless logger.nil?
230
- redis.set('corrected_rollup_including_disabled_checks', 'true')
231
- end
232
- end
233
- end
234
- end
@@ -1,425 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'active_support/time'
4
- require 'ice_cube'
5
- require 'flapjack/utility'
6
-
7
- module Flapjack
8
- module Data
9
- class NotificationRule
10
-
11
- extend Flapjack::Utility
12
-
13
- attr_accessor :id, :contact_id, :entities, :regex_entities, :tags, :regex_tags,
14
- :time_restrictions, :unknown_media, :warning_media, :critical_media,
15
- :unknown_blackhole, :warning_blackhole, :critical_blackhole
16
-
17
- def self.all(options = {})
18
- raise "Redis connection not set" unless redis = options[:redis]
19
- redis.keys("contact_notification_rules:*").inject([]) do |memo, contact_key|
20
- redis.smembers(contact_key).each do |rule_id|
21
- ret = self.find_by_id(rule_id, :redis => redis)
22
- memo << ret unless ret.nil?
23
- end
24
- memo
25
- end
26
- end
27
-
28
- def self.exists_with_id?(rule_id, options = {})
29
- raise "Redis connection not set" unless redis = options[:redis]
30
- raise "No id value passed" unless not (rule_id.nil? || rule_id == '')
31
- redis.exists("notification_rule:#{rule_id}")
32
- end
33
-
34
- def self.find_by_id(rule_id, options = {})
35
- raise "Redis connection not set" unless redis = options[:redis]
36
- raise "No id value passed" unless not (rule_id.nil? || rule_id == '')
37
-
38
- # sanity check
39
- return unless redis.exists("notification_rule:#{rule_id}")
40
-
41
- self.new({:id => rule_id.to_s}, {:redis => redis})
42
- end
43
-
44
- def self.find_by_ids(rule_ids, options = {})
45
- raise "Redis connection not set" unless redis = options[:redis]
46
-
47
- rule_ids.map do |id|
48
- self.find_by_id(id, options)
49
- end
50
- end
51
-
52
- # replacing save! etc
53
- def self.add(rule_data, options = {})
54
- raise "Redis connection not set" unless redis = options[:redis]
55
-
56
- if rule_data[:id] && self.find_by_id(rule_data[:id], :redis => redis)
57
- errors = ["a notification rule already exists with id '#{rule_data[:id]}'"]
58
- return errors
59
- end
60
- rule_id = rule_data[:id] || SecureRandom.uuid
61
-
62
- errors = self.add_or_update(rule_data.merge(:id => rule_id), :redis => redis, :logger => options[:logger])
63
- return errors unless errors.nil? || errors.empty?
64
-
65
- self.find_by_id(rule_id, :redis => redis)
66
- end
67
-
68
- def update(update_data, opts = {})
69
- [:entities, :regex_entities, :tags, :regex_tags,
70
- :time_restrictions, :unknown_media, :warning_media, :critical_media,
71
- :unknown_blackhole, :warning_blackhole, :critical_blackhole].each do |update_key|
72
-
73
- next if update_data.has_key?(update_key)
74
- update_data[update_key] = self.send(update_key)
75
- end
76
-
77
- update_data.update(:id => @id, :contact_id => @contact_id)
78
- errors = self.class.add_or_update(update_data, :redis => @redis, :logger => opts[:logger])
79
- return errors unless errors.nil? || errors.empty?
80
-
81
- refresh
82
- nil
83
- end
84
-
85
- # NB: ice_cube doesn't have much rule data validation, and has
86
- # problems with infinite loops if the data can't logically match; see
87
- # https://github.com/seejohnrun/ice_cube/issues/127 &
88
- # https://github.com/seejohnrun/ice_cube/issues/137
89
- # We may want to consider some sort of timeout-based check around
90
- # anything that could fall into that.
91
- #
92
- # We don't want to replicate IceCube's from_hash behaviour here,
93
- # but we do need to apply some sanity checking on the passed data.
94
- def self.time_restriction_to_icecube_schedule(tr, timezone, opts = {})
95
- return if tr.nil? || !tr.is_a?(Hash) ||
96
- timezone.nil? || !timezone.is_a?(ActiveSupport::TimeZone)
97
- prepared_restrictions = prepare_time_restriction(tr, timezone)
98
- return if prepared_restrictions.nil?
99
- IceCube::Schedule.from_hash(prepared_restrictions)
100
- rescue ArgumentError => ae
101
- if logger = opts[:logger]
102
- logger.error "Couldn't parse rule data #{e.class}: #{e.message}"
103
- logger.error prepared_restrictions.inspect
104
- logger.error e.backtrace.join("\n")
105
- end
106
- nil
107
- end
108
-
109
- def to_jsonapi(opts = {})
110
- json_data = self.class.hashify(:id, :tags, :regex_tags, :entities, :regex_entities,
111
- :time_restrictions, :unknown_media, :warning_media, :critical_media,
112
- :unknown_blackhole, :warning_blackhole, :critical_blackhole) {|k|
113
- case k
114
- when :tags, :regex_tags
115
- [k.to_s, self.send(k).to_a.sort]
116
- else
117
- [k.to_s, self.send(k)]
118
- end
119
- }.merge('links' => {'contacts' => [self.contact_id]})
120
-
121
- Flapjack.dump_json(json_data)
122
- end
123
-
124
- # If the rule has any entities, then one of them must match the event's entity
125
- def match_entity?(event_id)
126
- return true unless @entities && @entities.length > 0
127
- event_entity = event_id.split(':').first
128
- @entities.include?(event_entity)
129
- end
130
-
131
- # If the rule has any regex_entities, then all of them must match the
132
- # event's entity
133
- def match_regex_entities?(event_id)
134
- return true unless @regex_entities && @regex_entities.length > 0
135
- event_entity = event_id.split(':').first
136
- matches = 0
137
- @regex_entities.each do |regex_entity|
138
- matches += 1 if /#{regex_entity}/ === event_entity
139
- end
140
- matches >= @regex_entities.length
141
- end
142
-
143
- # If the rule has any tags, then they must all be present in the
144
- # event's tags
145
- def match_tags?(event_tags)
146
- return true unless @tags && @tags.length > 0
147
- @tags.subset?(event_tags)
148
- end
149
-
150
- # If the rule has any regex_tags, then they must all match at least
151
- # one of the event's tags
152
- def match_regex_tags?(event_tags)
153
- return true unless @regex_tags && @regex_tags.length > 0
154
- matches = 0
155
- @regex_tags.each do |regex_tag|
156
- matches += 1 if event_tags.any? { |event_tag| /#{regex_tag}/ === event_tag }
157
- end
158
- matches >= @regex_tags.length
159
- end
160
-
161
- def blackhole?(severity)
162
- ('unknown'.eql?(severity.downcase) && @unknown_blackhole) ||
163
- ('warning'.eql?(severity.downcase) && @warning_blackhole) ||
164
- ('critical'.eql?(severity.downcase) && @critical_blackhole)
165
- end
166
-
167
- def media_for_severity(severity)
168
- case severity
169
- when 'unknown'
170
- @unknown_media
171
- when 'warning'
172
- @warning_media
173
- when 'critical'
174
- @critical_media
175
- end
176
- end
177
-
178
- def is_specific?
179
- (!@entities.nil? && !@entities.empty?) ||
180
- (!@regex_entities.nil? && !@regex_entities.empty?) ||
181
- (!@tags.nil? && !@tags.empty?) ||
182
- (!@regex_tags.nil? && !@regex_tags.empty?)
183
- end
184
-
185
- private
186
-
187
- def initialize(rule_data, opts = {})
188
- @redis ||= opts[:redis]
189
- raise "a redis connection must be supplied" unless @redis
190
- @logger = opts[:logger]
191
- @id = rule_data[:id]
192
- refresh
193
- end
194
-
195
- def self.prevalidate_data(rule_data, options = {})
196
- errors = self.validate_data(preen(rule_data), options.merge(:id_not_required => true))
197
- end
198
-
199
- def self.preen(rule_data)
200
- # make some assumptions about the incoming data
201
- rule_data[:unknown_blackhole] = rule_data[:unknown_blackhole] || false
202
- rule_data[:warning_blackhole] = rule_data[:warning_blackhole] || false
203
- rule_data[:critical_blackhole] = rule_data[:critical_blackhole] || false
204
- if rule_data[:tags].is_a?(Array)
205
- rule_data[:tags] = Set.new(rule_data[:tags])
206
- end
207
- if rule_data[:regex_tags].is_a?(Array)
208
- rule_data[:regex_tags] = Set.new(rule_data[:regex_tags])
209
- end
210
- rule_data
211
- end
212
-
213
- def self.add_or_update(rule_data, options = {})
214
- redis = options[:redis]
215
- raise "a redis connection must be supplied" unless redis
216
- logger = options[:logger]
217
-
218
- rule_data = preen(rule_data)
219
- errors = self.validate_data(rule_data, options)
220
- return errors unless errors.nil? || errors.empty?
221
-
222
- # whitelisting fields, rather than passing through submitted data directly
223
- tag_data = rule_data[:tags].is_a?(Set) ? rule_data[:tags].to_a : nil
224
- regex_tag_data = rule_data[:regex_tags].is_a?(Set) ? rule_data[:regex_tags].to_a : nil
225
-
226
- json_rule_data = {
227
- :id => rule_data[:id].to_s,
228
- :contact_id => rule_data[:contact_id].to_s,
229
- :entities => Flapjack.dump_json(rule_data[:entities]),
230
- :regex_entities => Flapjack.dump_json(rule_data[:regex_entities]),
231
- :tags => Flapjack.dump_json(tag_data),
232
- :regex_tags => Flapjack.dump_json(regex_tag_data),
233
- :time_restrictions => Flapjack.dump_json(rule_data[:time_restrictions]),
234
- :unknown_media => Flapjack.dump_json(rule_data[:unknown_media]),
235
- :warning_media => Flapjack.dump_json(rule_data[:warning_media]),
236
- :critical_media => Flapjack.dump_json(rule_data[:critical_media]),
237
- :unknown_blackhole => rule_data[:unknown_blackhole],
238
- :warning_blackhole => rule_data[:warning_blackhole],
239
- :critical_blackhole => rule_data[:critical_blackhole],
240
- }
241
-
242
- logger.debug("NotificationRule#add_or_update json_rule_data: #{json_rule_data.inspect}") if logger
243
-
244
- redis.sadd("contact_notification_rules:#{json_rule_data[:contact_id]}",
245
- json_rule_data[:id])
246
- redis.hmset("notification_rule:#{json_rule_data[:id]}",
247
- *json_rule_data.flatten)
248
- nil
249
- end
250
-
251
- def self.prepare_time_restriction(time_restriction, timezone = nil)
252
- # this will hand back a 'deep' copy
253
- tr = symbolize(time_restriction)
254
-
255
- return unless (tr.has_key?(:start_time) || tr.has_key?(:start_date)) &&
256
- (tr.has_key?(:end_time) || tr.has_key?(:end_date))
257
-
258
- # exrules is deprecated in latest ice_cube, but may be stored in data
259
- # serialised from earlier versions of the gem
260
- # ( https://github.com/flapjack/flapjack/issues/715 )
261
- tr.delete(:exrules)
262
-
263
- parsed_time = proc {|tr, field|
264
- if t = tr.delete(field)
265
- t = t.dup
266
- t = t[:time] if t.is_a?(Hash)
267
-
268
- if t.is_a?(Time)
269
- t
270
- else
271
- begin; (timezone || Time).parse(t); rescue ArgumentError; nil; end
272
- end
273
- else
274
- nil
275
- end
276
- }
277
-
278
- start_time = parsed_time.call(tr, :start_date) || parsed_time.call(tr, :start_time)
279
- end_time = parsed_time.call(tr, :end_date) || parsed_time.call(tr, :end_time)
280
-
281
- return unless start_time && end_time
282
-
283
- tr[:start_time] = timezone ?
284
- {:time => start_time, :zone => timezone.name} :
285
- start_time
286
-
287
- tr[:end_time] = timezone ?
288
- {:time => end_time, :zone => timezone.name} :
289
- end_time
290
-
291
- tr[:duration] = end_time - start_time
292
-
293
- # check that rrule types are valid IceCube rule types
294
- return unless tr[:rrules].is_a?(Array) &&
295
- tr[:rrules].all? {|rr| rr.is_a?(Hash)} &&
296
- (tr[:rrules].map {|rr| rr[:rule_type]} -
297
- ['Daily', 'Hourly', 'Minutely', 'Monthly', 'Secondly',
298
- 'Weekly', 'Yearly']).empty?
299
-
300
- # rewrite Weekly to IceCube::WeeklyRule, etc
301
- tr[:rrules].each {|rrule|
302
- rrule[:rule_type] = "IceCube::#{rrule[:rule_type]}Rule"
303
- }
304
-
305
- # TODO does this need to check classes for the following values?
306
- # "validations": {
307
- # "day": [1,2,3,4,5]
308
- # },
309
- # "interval": 1,
310
- # "week_start": 0
311
-
312
- tr
313
- end
314
-
315
- VALIDATION_PROCS = {
316
- proc {|d| !d.has_key?(:entities) ||
317
- ( d[:entities].nil? ||
318
- d[:entities].is_a?(Array) &&
319
- d[:entities].all? {|e| e.is_a?(String)} ) } =>
320
- "entities must be a list of strings",
321
-
322
- proc {|d| !d.has_key?(:regex_entities) ||
323
- ( d[:regex_entities].nil? ||
324
- d[:regex_entities].is_a?(Array) &&
325
- d[:regex_entities].all? {|e| e.is_a?(String)} ) } =>
326
- "regex_entities must be a list of strings",
327
-
328
- proc {|d| !d.has_key?(:tags) ||
329
- ( d[:tags].nil? ||
330
- d[:tags].is_a?(Set) &&
331
- d[:tags].all? {|et| et.is_a?(String)} ) } =>
332
- "tags must be a tag_set of strings",
333
-
334
- proc {|d| !d.has_key?(:regex_tags) ||
335
- ( d[:regex_tags].nil? ||
336
- d[:regex_tags].is_a?(Set) &&
337
- d[:regex_tags].all? {|et| et.is_a?(String)} ) } =>
338
- "regex_tags must be a tag_set of strings",
339
-
340
- # conversion to a schedule needs a time zone, any one will do
341
- proc {|d| !d.has_key?(:time_restrictions) ||
342
- ( d[:time_restrictions].nil? ||
343
- d[:time_restrictions].all? {|tr|
344
- !!self.time_restriction_to_icecube_schedule(symbolize(tr), ActiveSupport::TimeZone['UTC'])
345
- } )
346
- } =>
347
- "time restrictions are invalid",
348
-
349
- # TODO should the media types be checked against a whitelist?
350
- proc {|d| !d.has_key?(:unknown_media) ||
351
- ( d[:unknown_media].nil? ||
352
- d[:unknown_media].is_a?(Array) &&
353
- d[:unknown_media].all? {|et| et.is_a?(String)} ) } =>
354
- "unknown_media must be a list of strings",
355
-
356
- proc {|d| !d.has_key?(:warning_media) ||
357
- ( d[:warning_media].nil? ||
358
- d[:warning_media].is_a?(Array) &&
359
- d[:warning_media].all? {|et| et.is_a?(String)} ) } =>
360
- "warning_media must be a list of strings",
361
-
362
- proc {|d| !d.has_key?(:critical_media) ||
363
- ( d[:critical_media].nil? ||
364
- d[:critical_media].is_a?(Array) &&
365
- d[:critical_media].all? {|et| et.is_a?(String)} ) } =>
366
- "critical_media must be a list of strings",
367
-
368
- proc {|d| !d.has_key?(:unknown_blackhole) ||
369
- [TrueClass, FalseClass].include?(d[:unknown_blackhole].class) } =>
370
- "unknown_blackhole must be true or false",
371
-
372
- proc {|d| !d.has_key?(:warning_blackhole) ||
373
- [TrueClass, FalseClass].include?(d[:warning_blackhole].class) } =>
374
- "warning_blackhole must be true or false",
375
-
376
- proc {|d| !d.has_key?(:critical_blackhole) ||
377
- [TrueClass, FalseClass].include?(d[:critical_blackhole].class) } =>
378
- "critical_blackhole must be true or false",
379
- }
380
-
381
- def self.validate_data(d, options = {})
382
- id_not_required = !!options[:id_not_required]
383
- # hash with validation => error_message
384
- validations = {}
385
- validations.merge!({ proc { d.has_key?(:id) } => "id not set"}) unless id_not_required
386
- validations.merge!(VALIDATION_PROCS)
387
-
388
- errors = validations.keys.inject([]) {|ret,vk|
389
- ret << "Rule #{validations[vk]}" unless vk.call(d)
390
- ret
391
- }
392
-
393
- return if errors.empty?
394
-
395
- if logger = options[:logger]
396
- error_str = errors.join(", ")
397
- logger.info "validation error: #{error_str}"
398
- logger.debug "rule failing validations: #{d.inspect}"
399
- end
400
- errors
401
- end
402
-
403
- def refresh
404
- rule_data = @redis.hgetall("notification_rule:#{@id}")
405
-
406
- @contact_id = rule_data['contact_id']
407
- tags = Flapjack.load_json(rule_data['tags'] || '')
408
- @tags = tags ? Set.new(tags) : nil
409
- regex_tags = Flapjack.load_json(rule_data['regex_tags'] || '')
410
- @regex_tags = regex_tags ? Set.new(regex_tags) : nil
411
- @entities = Flapjack.load_json(rule_data['entities'] || '')
412
- @regex_entities = Flapjack.load_json(rule_data['regex_entities'] || '')
413
- @time_restrictions = Flapjack.load_json(rule_data['time_restrictions'] || '')
414
- @unknown_media = Flapjack.load_json(rule_data['unknown_media'] || '')
415
- @warning_media = Flapjack.load_json(rule_data['warning_media'] || '')
416
- @critical_media = Flapjack.load_json(rule_data['critical_media'] || '')
417
- @unknown_blackhole = ((rule_data['unknown_blackhole'] || 'false').downcase == 'true')
418
- @warning_blackhole = ((rule_data['warning_blackhole'] || 'false').downcase == 'true')
419
- @critical_blackhole = ((rule_data['critical_blackhole'] || 'false').downcase == 'true')
420
- end
421
-
422
- end
423
- end
424
- end
425
-