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,186 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'sinatra/base'
4
-
5
- require 'flapjack/data/contact'
6
- require 'flapjack/data/notification_rule'
7
- require 'flapjack/data/semaphore'
8
-
9
- module Flapjack
10
-
11
- module Gateways
12
-
13
- class JSONAPI < Sinatra::Base
14
-
15
- module ContactMethods
16
-
17
- SEMAPHORE_CONTACT_MASS_UPDATE = 'contact_mass_update'
18
-
19
- module Helpers
20
-
21
- def obtain_semaphore(resource)
22
- semaphore = nil
23
- strikes = 0
24
- begin
25
- semaphore = Flapjack::Data::Semaphore.new(resource, :redis => redis, :expiry => 30)
26
- rescue Flapjack::Data::Semaphore::ResourceLocked
27
- strikes += 1
28
- raise Flapjack::Gateways::JSONAPI::ResourceLocked.new(resource) if strikes >= 3
29
- sleep 1
30
- retry
31
- end
32
- raise Flapjack::Gateways::JSONAPI::ResourceLocked.new(resource) if semaphore.nil?
33
- semaphore
34
- end
35
-
36
- def bulk_contact_operation(contact_ids, &block)
37
- semaphore = obtain_semaphore(SEMAPHORE_CONTACT_MASS_UPDATE)
38
-
39
- contacts_by_id = contact_ids.inject({}) do |memo, contact_id|
40
- # can't use find_contact here as that would halt immediately
41
- memo[contact_id] = Flapjack::Data::Contact.find_by_id(contact_id, :redis => redis, :logger => logger)
42
- memo
43
- end
44
-
45
- missing_ids = contacts_by_id.select {|k, v| v.nil? }.keys
46
- unless missing_ids.empty?
47
- semaphore.release
48
- raise Flapjack::Gateways::JSONAPI::ContactsNotFound.new(missing_ids)
49
- end
50
-
51
- block.call(contacts_by_id.select {|k, v| !v.nil? }.values)
52
- semaphore.release
53
- end
54
-
55
- end
56
-
57
- def self.registered(app)
58
- app.helpers Flapjack::Gateways::JSONAPI::Helpers
59
- app.helpers Flapjack::Gateways::JSONAPI::ContactMethods::Helpers
60
-
61
- app.post '/contacts' do
62
- contacts_data = params[:contacts]
63
-
64
- if contacts_data.nil? || !contacts_data.is_a?(Enumerable)
65
- halt err(422, "No valid contacts were submitted")
66
- end
67
-
68
- contacts_ids = contacts_data.reject {|c| c['id'].nil? }.
69
- map {|co| co['id'].to_s }
70
-
71
- semaphore = obtain_semaphore(SEMAPHORE_CONTACT_MASS_UPDATE)
72
-
73
- conflicted_ids = contacts_ids.find_all {|id|
74
- Flapjack::Data::Contact.exists_with_id?(id, :redis => redis)
75
- }
76
-
77
- unless conflicted_ids.empty?
78
- semaphore.release
79
- halt err(409, "Contacts already exist with the following IDs: " +
80
- conflicted_ids.join(', '))
81
- end
82
-
83
- contacts_data.each do |contact_data|
84
- unless contact_data['id']
85
- contact_data['id'] = SecureRandom.uuid
86
- end
87
- Flapjack::Data::Contact.add(contact_data, :redis => redis)
88
- end
89
-
90
- semaphore.release
91
-
92
- contact_ids = contacts_data.map {|c| c['id']}
93
-
94
- response.headers['Location'] = "#{base_url}/contacts/#{contact_ids.join(',')}"
95
- status 201
96
- Flapjack.dump_json(contact_ids)
97
- end
98
-
99
- # Returns all (/contacts) or some (/contacts/1,2,3) or one (/contacts/2) contact(s)
100
- # http://flapjack.io/docs/1.0/jsonapi/#contacts
101
- app.get %r{^/contacts(?:/)?([^/]+)?$} do
102
- requested_contacts = if params[:captures] && params[:captures][0]
103
- params[:captures][0].split(',').uniq
104
- else
105
- nil
106
- end
107
-
108
- contacts = if requested_contacts
109
- Flapjack::Data::Contact.find_by_ids(requested_contacts, :logger => logger, :redis => redis)
110
- else
111
- Flapjack::Data::Contact.all(:redis => redis).reject {|c| c.id.nil? || c.id.empty? }
112
- end
113
- contacts.compact!
114
-
115
- if requested_contacts && contacts.empty?
116
- raise Flapjack::Gateways::JSONAPI::ContactsNotFound.new(requested_contacts)
117
- end
118
-
119
- entity_ids = contacts.empty? ? [] : Flapjack::Data::Contact.entity_ids_for(contacts.map(&:id), :redis => redis)
120
-
121
- contacts_json = contacts.collect {|contact|
122
- contact.to_jsonapi(:entity_ids => entity_ids[contact.id])
123
- }.join(", ")
124
-
125
- '{"contacts":[' + contacts_json + ']}'
126
- end
127
-
128
- app.patch '/contacts/:id' do
129
- bulk_contact_operation(params[:id].split(',')) do |contacts|
130
- contacts.each do |contact|
131
- apply_json_patch('contacts') do |op, property, linked, value|
132
- case op
133
- when 'replace'
134
- if ['first_name', 'last_name', 'email', 'timezone'].include?(property)
135
- contact.update(property => value)
136
- end
137
- when 'add'
138
- case linked
139
- when 'entities'
140
- entity = Flapjack::Data::Entity.find_by_id(value, :redis => redis)
141
- contact.add_entity(entity) unless entity.nil?
142
- when 'notification_rules'
143
- notification_rule = Flapjack::Data::NotificationRule.find_by_id(value, :redis => redis)
144
- unless notification_rule.nil?
145
- contact.grab_notification_rule(notification_rule)
146
- end
147
- # when 'media' # not supported yet due to id brokenness
148
- end
149
- when 'remove'
150
- case linked
151
- when 'entities'
152
- entity = Flapjack::Data::Entity.find_by_id(value, :redis => redis)
153
- contact.remove_entity(entity) unless entity.nil?
154
- when 'notification_rules'
155
- notification_rule = Flapjack::Data::NotificationRule.find_by_id(value, :redis => redis)
156
- unless notification_rule.nil?
157
- contact.delete_notification_rule(notification_rule)
158
- end
159
- # when 'media' # not supported yet due to id brokenness
160
- end
161
- end
162
- end
163
- end
164
- end
165
-
166
- status 204
167
- end
168
-
169
- # Delete one or more contacts
170
- app.delete '/contacts/:id' do
171
- bulk_contact_operation(params[:id].split(',')) do |contacts|
172
- contacts.each {|contact| contact.delete!}
173
- end
174
-
175
- status 204
176
- end
177
-
178
- end
179
-
180
- end
181
-
182
- end
183
-
184
- end
185
-
186
- end
@@ -1,223 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'sinatra/base'
4
-
5
- require 'flapjack/data/entity'
6
- require 'flapjack/data/entity_check'
7
-
8
- module Flapjack
9
-
10
- module Gateways
11
-
12
- class JSONAPI < Sinatra::Base
13
-
14
- module EntityMethods
15
-
16
- module Helpers
17
-
18
- def checks_for_entity_ids(entity_ids)
19
- return if entity_ids.nil?
20
- entity_ids.inject([]) do |memo, entity_id|
21
- entity = find_entity_by_id(entity_id)
22
- check_names = entity.check_list.sort
23
- check_names.each do |check_name|
24
- memo << find_entity_check(entity, check_name)
25
- end
26
- memo
27
- end
28
- end
29
- end
30
-
31
- def self.registered(app)
32
- app.helpers Flapjack::Gateways::JSONAPI::Helpers
33
- app.helpers Flapjack::Gateways::JSONAPI::EntityMethods::Helpers
34
-
35
- # Returns all (/entities) or some (/entities/A,B,C) or one (/entities/A) contact(s)
36
- # NB: only works with good data -- i.e. entity must have an id
37
- app.get %r{^/entities(?:/)?([^/]+)?$} do
38
- requested_entities = if params[:captures] && params[:captures][0]
39
- params[:captures][0].split(',').uniq
40
- else
41
- nil
42
- end
43
-
44
- entities = if requested_entities
45
- Flapjack::Data::Entity.find_by_ids(requested_entities, :logger => logger, :redis => redis)
46
- else
47
- enabled = if params.has_key?(:enabled)
48
- case params[:enabled].downcase
49
- when '0', 'f', 'false', 'n', 'no'
50
- false
51
- when '1', 't', 'true', 'y', 'yes'
52
- true
53
- else
54
- nil
55
- end
56
- else
57
- nil
58
- end
59
-
60
- Flapjack::Data::Entity.all(:enabled => enabled,
61
- :redis => redis).reject {|e| e.id.nil? || e.id.empty? }
62
- end
63
- entities.compact!
64
-
65
- if requested_entities && entities.empty?
66
- raise Flapjack::Gateways::JSONAPI::EntitiesNotFound.new(requested_entities)
67
- end
68
-
69
- entity_ids = entities.map(&:id)
70
- linked_contact_ids = entities.empty? ? [] :
71
- Flapjack::Data::Entity.contact_ids_for(entity_ids, :redis => redis)
72
- linked_check_ids = entities.empty? ? [] :
73
- Flapjack::Data::Entity.check_ids_for(entity_ids, :redis => redis)
74
-
75
- entities_json = entities.collect {|entity|
76
- entity_id = entity.id
77
- entity.to_jsonapi(:contact_ids => linked_contact_ids[entity_id],
78
- :check_ids => linked_check_ids[entity_id] )
79
- }.join(",")
80
-
81
- '{"entities":[' + entities_json + ']}'
82
- end
83
-
84
- app.post '/entities' do
85
- entities = wrapped_params('entities')
86
- return err(403, "Entity with a nil id detected") if entities.any? {|e| e['id'].nil?}
87
-
88
- entity_ids = entities.collect{|entity_data|
89
- Flapjack::Data::Entity.add(entity_data, :redis => redis)
90
- entity_data['id']
91
- }
92
-
93
- response.headers['Location'] = "#{request.base_url}/entities/#{entity_ids.join(',')}"
94
- status 201
95
- Flapjack.dump_json(entity_ids)
96
- end
97
-
98
- app.patch '/entities/:id' do
99
- params[:id].split(',').collect {|entity_id|
100
- find_entity_by_id(entity_id)
101
- }.each do |entity|
102
- apply_json_patch('entities') do |op, property, linked, value|
103
- case op
104
- when 'replace'
105
- if 'name'.eql?(property)
106
- name = entity.name
107
- if name != value
108
- existing = Flapjack::Data::Entity.find_by_name(value, :redis => redis)
109
- Flapjack::Data::Entity.send(existing.nil? ? :rename : :merge,
110
- name, value, :redis => redis)
111
- end
112
- end
113
- when 'add'
114
- case linked
115
- when 'contacts'
116
- contact = Flapjack::Data::Contact.find_by_id(value, :redis => redis)
117
- contact.add_entity(entity) unless contact.nil?
118
- when 'tags'
119
- value.respond_to?(:each) ? entity.add_tags(*value) :
120
- entity.add_tags(value)
121
- end
122
- when 'remove'
123
- case linked
124
- when 'contacts'
125
- contact = Flapjack::Data::Contact.find_by_id(value, :redis => redis)
126
- contact.remove_entity(entity) unless contact.nil?
127
- when 'tags'
128
- value.respond_to?(:each) ? entity.delete_tags(*value) :
129
- entity.delete_tags(value)
130
- end
131
- end
132
- end
133
- end
134
-
135
- status 204
136
- end
137
-
138
- # create a scheduled maintenance period for a check on an entity
139
- app.post %r{^/scheduled_maintenances/entities/([^/]+)$} do
140
- scheduled_maintenances = wrapped_params('scheduled_maintenances')
141
- checks_for_entity_ids(params[:captures][0].split(',')).each do |check|
142
- scheduled_maintenances.each do |wp|
143
- start_time = validate_and_parsetime(wp['start_time'])
144
- halt( err(403, "start time must be provided") ) unless start_time
145
- check.create_scheduled_maintenance(start_time,
146
- wp['duration'].to_i, :summary => wp['summary'])
147
- end
148
- end
149
-
150
- status 204
151
- end
152
-
153
- # create an acknowledgement for a service on an entity
154
- # NB currently, this does not acknowledge a specific failure event, just
155
- # the entity-check as a whole
156
- app.post %r{^/unscheduled_maintenances/entities/([^/]+)$} do
157
- unscheduled_maintenances = wrapped_params('unscheduled_maintenances', false)
158
- checks_for_entity_ids(params[:captures][0].split(',')).each do |check|
159
- unscheduled_maintenances.each do |wp|
160
- dur = wp['duration'] ? wp['duration'].to_i : nil
161
- duration = (dur.nil? || (dur <= 0)) ? (4 * 60 * 60) : dur
162
- summary = wp['summary']
163
-
164
- opts = {:duration => duration}
165
- opts[:summary] = summary if summary
166
-
167
- Flapjack::Data::Event.create_acknowledgement(
168
- check.entity_name, check.check, {:redis => redis}.merge(opts))
169
- end
170
- end
171
-
172
- status 204
173
- end
174
-
175
- app.patch %r{^/unscheduled_maintenances/entities/([^/]+)$} do
176
- checks_for_entity_ids( params[:captures][0].split(',') ).each do |check|
177
- apply_json_patch('unscheduled_maintenances') do |op, property, linked, value|
178
- case op
179
- when 'replace'
180
- if ['end_time'].include?(property)
181
- end_time = validate_and_parsetime(value)
182
- check.end_unscheduled_maintenance(end_time.to_i)
183
- end
184
- end
185
- end
186
- end
187
- status 204
188
- end
189
-
190
- app.delete %r{^/scheduled_maintenances/entities/([^/]+)$} do
191
- start_time = validate_and_parsetime(params[:start_time])
192
- halt( err(403, "start time must be provided") ) unless start_time
193
-
194
- checks_for_entity_ids(params[:captures][0].split(',')).each do |check|
195
- check.end_scheduled_maintenance(start_time.to_i)
196
- end
197
- status 204
198
- end
199
-
200
- app.post %r{^/test_notifications/entities/([^/]+)$} do
201
- test_notifications = wrapped_params('test_notifications', false)
202
- checks_for_entity_ids(params[:captures][0].split(',')).each do |check|
203
- test_notifications.each do |wp|
204
- summary = wp['summary'] ||
205
- "Testing notifications to all contacts interested in entity #{check.entity.name}"
206
- Flapjack::Data::Event.test_notifications(
207
- check.entity_name, check.check,
208
- :summary => summary,
209
- :redis => redis)
210
- end
211
- end
212
- status 204
213
- end
214
-
215
- end
216
-
217
- end
218
-
219
- end
220
-
221
- end
222
-
223
- end
@@ -1,185 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'sinatra/base'
4
-
5
- require 'flapjack/data/contact'
6
-
7
- module Flapjack
8
-
9
- module Gateways
10
-
11
- class JSONAPI < Sinatra::Base
12
-
13
- module MediumMethods
14
-
15
- SEMAPHORE_CONTACT_MASS_UPDATE = 'contact_mass_update'
16
-
17
- module Helpers
18
-
19
- def obtain_semaphore(resource)
20
- semaphore = nil
21
- strikes = 0
22
- begin
23
- semaphore = Flapjack::Data::Semaphore.new(resource, :redis => redis, :expiry => 30)
24
- rescue Flapjack::Data::Semaphore::ResourceLocked
25
- strikes += 1
26
- raise Flapjack::Gateways::JSONAPI::ResourceLocked.new(resource) unless strikes < 3
27
- sleep 1
28
- retry
29
- end
30
- raise Flapjack::Gateways::JSONAPI::ResourceLocked.new(resource) unless semaphore
31
- semaphore
32
- end
33
-
34
- # TODO validate that media type exists in redis
35
- def split_media_ids(media_ids)
36
-
37
- contact_cache = {}
38
-
39
- known_media_identifiers = Flapjack::Data::Contact::ALL_MEDIA.reject{|m| m == 'pagerduty'}.join('|')
40
- media_ids.split(',').uniq.collect do |m_id|
41
- m_id =~ /\A(.+)_(#{known_media_identifiers})\z/
42
-
43
- contact_id = $1
44
- media_type = $2
45
- halt err(422, "Could not get contact_id from media_id '#{m_id}'") if contact_id.nil?
46
- halt err(422, "Could not get media type from media_id '#{m_id}'") if media_type.nil?
47
-
48
- contact_cache[contact_id] ||= find_contact(contact_id)
49
-
50
- {:contact => contact_cache[contact_id], :type => media_type}
51
- end
52
- end
53
-
54
- end
55
-
56
- def self.registered(app)
57
- app.helpers Flapjack::Gateways::JSONAPI::Helpers
58
- app.helpers Flapjack::Gateways::JSONAPI::MediumMethods::Helpers
59
-
60
- # Creates media records for a contact
61
- app.post '/contacts/:contact_id/media' do
62
- media_data = params[:media]
63
-
64
- if media_data.nil? || !media_data.is_a?(Enumerable)
65
- halt err(422, "No valid media were submitted")
66
- end
67
-
68
- media_id_re = /^#{params[:contact_id]}_(?:#{Flapjack::Data::Contact::ALL_MEDIA.join('|')}$)/
69
-
70
- unless media_data.all? {|m| m['id'].nil? || media_id_re === m['id'] }
71
- halt err(422, "Media creation cannot include non-conformant IDs")
72
- end
73
-
74
- semaphore = obtain_semaphore(SEMAPHORE_CONTACT_MASS_UPDATE)
75
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
76
- if contact.nil?
77
- semaphore.release
78
- halt err(422, "Contact id: '#{params[:contact_id]}' could not be loaded")
79
- end
80
-
81
- media_data.each do |medium_data|
82
- type = medium_data['type']
83
- contact.set_address_for_media(type, medium_data['address'])
84
- contact.set_interval_for_media(type, medium_data['interval'])
85
- contact.set_rollup_threshold_for_media(type, medium_data['rollup_threshold'])
86
- medium_data['id'] = "#{contact.id}_#{type}"
87
- end
88
-
89
- semaphore.release
90
-
91
- media_ids = media_data.collect {|md| md['id']}
92
-
93
- status 201
94
- response.headers['Location'] = "#{base_url}/media/#{media_ids.join(',')}"
95
- Flapjack.dump_json(media_ids)
96
- end
97
-
98
- # get one or more media records; media ids are, for Flapjack
99
- # v1, composed of "#{contact.id}_#{media_type}"
100
- app.get %r{^/media(?:/)?([^/]+)?$} do
101
- media_list_cache = {}
102
- contact_media = if params[:captures] && params[:captures][0]
103
- split_media_ids(params[:captures][0])
104
- else
105
- Flapjack::Data::Contact.all(:redis => redis).collect do |contact|
106
- media_list_cache[contact.id] ||= contact.media_list
107
- media_list_cache[contact.id].collect do |media_type|
108
- {:contact => contact, :type => media_type}
109
- end
110
- end.flatten(1)
111
- end
112
-
113
- media_data = contact_media.inject([]) do |memo, contact_media_type|
114
- contact = contact_media_type[:contact]
115
- media_type = contact_media_type[:type]
116
-
117
- media_list_cache[contact.id] ||= contact.media_list
118
- if media_list_cache[contact.id].include?(media_type)
119
- medium_id = "#{contact.id}_#{media_type}"
120
- int = contact.media_intervals[media_type]
121
- rut = contact.media_rollup_thresholds[media_type]
122
- memo <<
123
- {:id => medium_id,
124
- :type => media_type,
125
- :address => contact.media[media_type],
126
- :interval => int.nil? ? nil : int.to_i,
127
- :rollup_threshold => rut.nil? ? nil : rut.to_i,
128
- :links => {:contacts => [contact.id]}}
129
- end
130
-
131
- memo
132
- end
133
-
134
- '{"media":' + Flapjack.dump_json(media_data) + '}'
135
- end
136
-
137
- # update one or more media records; media ids are, for Flapjack
138
- # v1, composed of "#{contact.id}_#{media_type}"
139
- app.patch '/media/:id' do
140
- media_list_cache = {}
141
- split_media_ids(params[:id]).each do |contact_media_type|
142
- contact = contact_media_type[:contact]
143
- media_type = contact_media_type[:type]
144
- media_list_cache[contact.id] ||= contact.media_list
145
- next unless media_list_cache[contact.id].include?(media_type)
146
- apply_json_patch('media') do |op, property, linked, value|
147
- if 'replace'.eql?(op)
148
- case property
149
- when 'address'
150
- contact.set_address_for_media(media_type, value)
151
- when 'interval'
152
- contact.set_interval_for_media(media_type, value)
153
- when 'rollup_threshold'
154
- contact.set_rollup_threshold_for_media(media_type, value)
155
- end
156
- end
157
- end
158
- end
159
-
160
- status 204
161
- end
162
-
163
- # delete one or more media records; media ids are, for Flapjack
164
- # v1, composed of "#{contact.id}_#{media_type}"
165
- app.delete '/media/:id' do
166
- media_list_cache = {}
167
- split_media_ids(params[:id]).each do |contact_media_type|
168
- contact = contact_media_type[:contact]
169
- media_type = contact_media_type[:type]
170
- media_list_cache[contact.id] ||= contact.media_list
171
- next unless media_list_cache[contact.id].include?(media_type)
172
- contact.remove_media(media_type)
173
- end
174
- status 204
175
- end
176
-
177
- end
178
-
179
- end
180
-
181
- end
182
-
183
- end
184
-
185
- end