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,318 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'em-hiredis'
4
- require 'em-synchrony'
5
- require 'em-synchrony/em-http'
6
-
7
- require 'flapjack/data/entity_check'
8
- require 'flapjack/data/alert'
9
- require 'flapjack/redis_pool'
10
- require 'flapjack/utility'
11
-
12
- module Flapjack
13
-
14
- module Gateways
15
-
16
- class Pagerduty
17
- PAGERDUTY_EVENTS_API_URL = 'https://events.pagerduty.com/generic/2010-04-15/create_event.json'
18
- SEM_PAGERDUTY_ACKS_RUNNING = 'sem_pagerduty_acks_running'
19
- SEM_PAGERDUTY_ACKS_RUNNING_TIMEOUT = 3600
20
-
21
- include Flapjack::Utility
22
-
23
- def initialize(opts = {})
24
- @config = opts[:config]
25
- @logger = opts[:logger]
26
- @redis_config = opts[:redis_config] || {}
27
- @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2, :logger => @logger)
28
-
29
- @logger.debug("New Pagerduty pikelet with the following options: #{@config.inspect}")
30
-
31
- @pagerduty_acks_started = nil
32
- super()
33
- end
34
-
35
- def stop
36
- @logger.info("stopping")
37
- @should_quit = true
38
-
39
- redis_uri = @redis_config[:path] ||
40
- "redis://#{@redis_config[:host] || '127.0.0.1'}:#{@redis_config[:port] || '6379'}/#{@redis_config[:db] || '0'}"
41
- shutdown_redis = EM::Hiredis.connect(redis_uri)
42
- shutdown_redis.rpush(@config['queue'], Flapjack.dump_json('notification_type' => 'shutdown'))
43
- end
44
-
45
- def start
46
- @logger.info("starting")
47
- while not test_pagerduty_connection and not @should_quit do
48
- @logger.error("Can't connect to the pagerduty API, retrying after 10 seconds")
49
- EM::Synchrony.sleep(10)
50
- end
51
-
52
- # TODO: only clear this if there isn't another pagerduty gateway instance running
53
- # or better, include an instance ID in the semaphore key name
54
- @redis.del(SEM_PAGERDUTY_ACKS_RUNNING)
55
-
56
- acknowledgement_timer = EM::Synchrony.add_periodic_timer(10) do
57
- find_pagerduty_acknowledgements_if_safe
58
- end
59
-
60
- queue = @config['queue']
61
- events = {}
62
-
63
- until @should_quit
64
- @logger.debug("pagerduty gateway is going into blpop mode on #{queue}")
65
- events[queue] = @redis.blpop(queue, 0)
66
- event_json = events[queue][1]
67
-
68
- begin
69
- event = Flapjack.load_json(event_json)
70
- @logger.debug("pagerduty notification event received: " + event.inspect)
71
-
72
- if 'shutdown'.eql?(event['notification_type'])
73
- @logger.debug("@should_quit: #{@should_quit}")
74
- next
75
- end
76
-
77
- alert = Flapjack::Data::Alert.new(event, :logger => @logger)
78
- @logger.debug("processing pagerduty notification service_key: #{alert.address}, entity: #{alert.entity}, " +
79
- "check: '#{alert.check}', state: #{alert.state}, summary: #{alert.summary}")
80
-
81
- message_template_erb, message_template =
82
- load_template(@config['templates'], 'alert',
83
- 'text', File.join(File.dirname(__FILE__), 'pagerduty'))
84
-
85
- @alert = alert
86
- bnd = binding
87
-
88
- begin
89
- message = message_template_erb.result(bnd).chomp
90
- rescue => e
91
- @logger.error "Error while executing the ERB for a pagerduty message, " +
92
- "ERB being executed: #{message_template}"
93
- raise
94
- end
95
-
96
- pagerduty_type = case alert.type
97
- when 'acknowledgement'
98
- 'acknowledge'
99
- when 'problem'
100
- 'trigger'
101
- when 'recovery'
102
- 'resolve'
103
- when 'test'
104
- 'trigger'
105
- end
106
-
107
- # Setting the HOSTNAME and the SERVICE makes them visible in the Pagerduty UI
108
- pagerduty_event = { 'service_key' => alert.address,
109
- 'incident_key' => alert.event_id,
110
- 'event_type' => pagerduty_type,
111
- 'description' => message,
112
- 'details' => {'HOSTNAME' => alert.entity,
113
- 'SERVICE' => alert.check}}
114
-
115
- send_pagerduty_event(pagerduty_event)
116
- alert.record_send_success!
117
- rescue => e
118
- @logger.error "Error generating or dispatching pagerduty message: #{e.class}: #{e.message}\n" +
119
- e.backtrace.join("\n")
120
- @logger.debug "Message that could not be processed: \n" + event_json
121
- end
122
- end
123
-
124
- acknowledgement_timer.cancel
125
- end
126
-
127
- # considering this as part of the public API -- exposes it for testing.
128
- def find_pagerduty_acknowledgements_if_safe
129
-
130
- # ensure we're the only instance of the pagerduty acknowledgement check running (with a naive
131
- # timeout of five minutes to guard against stale locks caused by crashing code) either in this
132
- # process or in other processes
133
- if (@pagerduty_acks_started and @pagerduty_acks_started >
134
- (Time.now.to_i - SEM_PAGERDUTY_ACKS_RUNNING_TIMEOUT)) or
135
- @redis.get(SEM_PAGERDUTY_ACKS_RUNNING) == 'true'
136
- @logger.debug("skipping looking for acks in pagerduty as this is already happening")
137
- return
138
- end
139
-
140
- @pagerduty_acks_started = Time.now.to_i
141
- @redis.set(SEM_PAGERDUTY_ACKS_RUNNING, 'true')
142
- @redis.expire(SEM_PAGERDUTY_ACKS_RUNNING, SEM_PAGERDUTY_ACKS_RUNNING_TIMEOUT)
143
-
144
- find_pagerduty_acknowledgements
145
-
146
- @redis.del(SEM_PAGERDUTY_ACKS_RUNNING)
147
- @pagerduty_acks_started = nil
148
- end
149
-
150
- private
151
-
152
- def test_pagerduty_connection
153
- noop = { "service_key" => "11111111111111111111111111111111",
154
- "incident_key" => "Flapjack is running a NOOP",
155
- "event_type" => "nop",
156
- "description" => "I love APIs with noops." }
157
- code, results = send_pagerduty_event(noop)
158
- return true if code == 200 && results['status'] =~ /success/i
159
- @logger.error "Error: test_pagerduty_connection: API returned #{code.to_s} #{results.inspect}"
160
- false
161
- end
162
-
163
- def send_pagerduty_event(event)
164
- options = { :body => Flapjack.dump_json(event) }
165
- http = EM::HttpRequest.new(PAGERDUTY_EVENTS_API_URL).post(options)
166
- response = Flapjack.load_json(http.response)
167
- status = http.response_header.status
168
- @logger.debug "send_pagerduty_event got a return code of #{status.to_s} - #{response.inspect}"
169
- unless status == 200
170
- raise "Error sending event to pagerduty: status: #{status.to_s} - #{response.inspect}" +
171
- " posted data: #{options[:body]}"
172
- end
173
- [status, response]
174
- end
175
-
176
- def find_pagerduty_acknowledgements
177
- unacknowledged_failing_checks = Flapjack::Data::EntityCheck.unacknowledged_failing(:redis => @redis)
178
- if unacknowledged_failing_checks.empty?
179
- @logger.debug("skipping looking for acks in pagerduty as there are no unacknowledged failing checks")
180
- return nil
181
- else
182
- @logger.debug("looking for acks in pagerduty for unack'd problems")
183
- end
184
-
185
- @logger.debug "found #{unacknowledged_failing_checks.length} unacknowledged failing checks as follows: " +
186
- unacknowledged_failing_checks.map {|c| "#{c.entity_name}:#{c.check}"}.join(', ')
187
-
188
- unacknowledged_failing_checks.each do |entity_check|
189
-
190
- # If more than one contact for this entity_check has pagerduty
191
- # credentials then there'll be one hash in the array for each set of
192
- # credentials.
193
- ec_credentials = entity_check.contacts.inject([]) {|ret, contact|
194
- cred = contact.pagerduty_credentials
195
- ret << cred if cred
196
- ret
197
- }
198
-
199
- check = entity_check.check
200
- entity_name = entity_check.entity_name
201
-
202
- if ec_credentials.empty?
203
- @logger.debug("No pagerduty credentials found for #{entity_name}:#{check}, skipping")
204
- next
205
- end
206
-
207
- # FIXME: try each set of credentials until one works (may have stale contacts turning up)
208
- options = ec_credentials.first.merge('check' => "#{entity_name}:#{check}")
209
-
210
- # check again that the check is still unacknowledged
211
- if entity_check.in_unscheduled_maintenance?
212
- # skip this one
213
- @logger.warn "#{entity_name}:#{check} seems to have been acknowledged by " +
214
- "some other process while I've been running. Cancelling acknowledgement creation"
215
- next
216
- end
217
-
218
- # check again that the check is still failing
219
- unless entity_check.failed?
220
- # skip this one
221
- @logger.warn "#{entity_name}:#{check} seems to have recovered " +
222
- "while I've been running. Cancelling acknowledgement creation"
223
- next
224
- end
225
-
226
- acknowledged = pagerduty_acknowledged?(options)
227
- if acknowledged.nil?
228
- @logger.debug "#{entity_name}:#{check} is not acknowledged in pagerduty, skipping"
229
- next
230
- end
231
-
232
- pg_acknowledged_by = acknowledged[:pg_acknowledged_by]
233
- @logger.info "#{entity_name}:#{check} is acknowledged in pagerduty, creating flapjack acknowledgement... "
234
- who_text = ""
235
- if !pg_acknowledged_by.nil? && !pg_acknowledged_by['name'].nil?
236
- who_text = " by #{pg_acknowledged_by['name']}"
237
- end
238
-
239
- # FIXME: decide where the default acknowledgement period should reside and use it
240
- # everywhere ... a case for moving configuration into redis (from config file) perhaps?
241
- four_hours = 4 * 60 * 60
242
- Flapjack::Data::Event.create_acknowledgement(
243
- entity_name, check,
244
- :summary => "Acknowledged on PagerDuty" + who_text,
245
- :duration => four_hours,
246
- :redis => @redis)
247
- end
248
-
249
- end
250
-
251
- def pagerduty_acknowledged?(opts)
252
- subdomain = opts['subdomain']
253
- token = opts['token']
254
- username = opts['username']
255
- password = opts['password']
256
- check = opts['check']
257
-
258
- unless subdomain && (token || (username && password)) && check
259
- @logger.warn("pagerduty_acknowledged?: Unable to look for acknowledgements on pagerduty" +
260
- " as the following options are required:" +
261
- " subdomain (#{subdomain}), token (#{token}) or" +
262
- " username (#{username}) and password (#{password}), check (#{check})")
263
- return nil
264
- end
265
-
266
- t = Time.now.utc
267
-
268
- url = 'https://' + subdomain + '.pagerduty.com/api/v1/incidents'
269
- query = { 'fields' => 'incident_number,status,last_status_change_by',
270
- 'since' => (t - (60*60*24*7)).iso8601, # the last week
271
- 'until' => (t + (60*60*24)).iso8601, # 1 day in the future
272
- 'incident_key' => check,
273
- 'status' => 'acknowledged' }
274
-
275
- auth_header = if token && token.length > 0
276
- "Token token=#{token}"
277
- else
278
- [username, password]
279
- end
280
-
281
- options = { :head => { 'authorization' => auth_header },
282
- :query => query }
283
-
284
- @logger.debug("pagerduty_acknowledged?: request to #{url}")
285
- @logger.debug("pagerduty_acknowledged?: query: #{query.inspect}")
286
- @logger.debug("pagerduty_acknowledged?: auth: #{options[:head].inspect}")
287
-
288
- http = EM::HttpRequest.new(url).get(options)
289
- begin
290
- response = Flapjack.load_json(http.response)
291
- rescue Oj::Error
292
- @logger.error("failed to parse json from a post to #{url} ... response headers and body follows...")
293
- end
294
- status = http.response_header.status
295
- @logger.debug(http.response_header.inspect)
296
- @logger.debug(http.response)
297
-
298
- @logger.debug("pagerduty_acknowledged?: decoded response as: #{response.inspect}")
299
- if response.nil?
300
- @logger.error('no valid response received from pagerduty!')
301
- return nil
302
- end
303
-
304
- if response['incidents'].nil?
305
- @logger.error('no incidents found in response')
306
- return nil
307
- end
308
-
309
- return nil if response['incidents'].empty?
310
-
311
- {:pg_acknowledged_by => response['incidents'].first['last_status_change_by']}
312
- end
313
-
314
- end
315
-
316
- end
317
-
318
- end
@@ -1,10 +0,0 @@
1
- <%= @alert.type_sentence_case %>: "<%= @alert.check %>" on <%= @alert.entity -%>
2
- <% unless ['acknowledgement', 'test'].include?(@alert.notification_type) -%>
3
- is <%= @alert.state_title_case -%>
4
- <% end -%>
5
- <% if ['acknowledgement'].include?(@alert.type) -%>
6
- has been acknowledged, unscheduled maintenance created for <%= time_period_in_words(@alert.acknowledgement_duration) -%>
7
- <% end -%>
8
- <% if @alert.summary && !@alert.summary.empty? -%>
9
- , <%= @alert.summary -%>
10
- <% end -%>
@@ -1,87 +0,0 @@
1
- .form-control .select2-choice {
2
- border: 0;
3
- border-radius: 2px;
4
- }
5
-
6
- .form-control .select2-choice .select2-arrow {
7
- border-radius: 0 2px 2px 0;
8
- }
9
-
10
- .form-control.select2-container {
11
- height: auto !important;
12
- padding: 0px;
13
- }
14
-
15
- .form-control.select2-container.select2-dropdown-open {
16
- border-color: #5897FB;
17
- border-radius: 3px 3px 0 0;
18
- }
19
-
20
- .form-control .select2-container.select2-dropdown-open .select2-choices {
21
- border-radius: 3px 3px 0 0;
22
- }
23
-
24
- .form-control.select2-container .select2-choices {
25
- border: 0 !important;
26
- border-radius: 3px;
27
- }
28
-
29
- .control-group.warning .select2-container .select2-choice,
30
- .control-group.warning .select2-container .select2-choices,
31
- .control-group.warning .select2-container-active .select2-choice,
32
- .control-group.warning .select2-container-active .select2-choices,
33
- .control-group.warning .select2-dropdown-open.select2-drop-above .select2-choice,
34
- .control-group.warning .select2-dropdown-open.select2-drop-above .select2-choices,
35
- .control-group.warning .select2-container-multi.select2-container-active .select2-choices {
36
- border: 1px solid #C09853 !important;
37
- }
38
-
39
- .control-group.warning .select2-container .select2-choice div {
40
- border-left: 1px solid #C09853 !important;
41
- background: #FCF8E3 !important;
42
- }
43
-
44
- .control-group.error .select2-container .select2-choice,
45
- .control-group.error .select2-container .select2-choices,
46
- .control-group.error .select2-container-active .select2-choice,
47
- .control-group.error .select2-container-active .select2-choices,
48
- .control-group.error .select2-dropdown-open.select2-drop-above .select2-choice,
49
- .control-group.error .select2-dropdown-open.select2-drop-above .select2-choices,
50
- .control-group.error .select2-container-multi.select2-container-active .select2-choices {
51
- border: 1px solid #B94A48 !important;
52
- }
53
-
54
- .control-group.error .select2-container .select2-choice div {
55
- border-left: 1px solid #B94A48 !important;
56
- background: #F2DEDE !important;
57
- }
58
-
59
- .control-group.info .select2-container .select2-choice,
60
- .control-group.info .select2-container .select2-choices,
61
- .control-group.info .select2-container-active .select2-choice,
62
- .control-group.info .select2-container-active .select2-choices,
63
- .control-group.info .select2-dropdown-open.select2-drop-above .select2-choice,
64
- .control-group.info .select2-dropdown-open.select2-drop-above .select2-choices,
65
- .control-group.info .select2-container-multi.select2-container-active .select2-choices {
66
- border: 1px solid #3A87AD !important;
67
- }
68
-
69
- .control-group.info .select2-container .select2-choice div {
70
- border-left: 1px solid #3A87AD !important;
71
- background: #D9EDF7 !important;
72
- }
73
-
74
- .control-group.success .select2-container .select2-choice,
75
- .control-group.success .select2-container .select2-choices,
76
- .control-group.success .select2-container-active .select2-choice,
77
- .control-group.success .select2-container-active .select2-choices,
78
- .control-group.success .select2-dropdown-open.select2-drop-above .select2-choice,
79
- .control-group.success .select2-dropdown-open.select2-drop-above .select2-choices,
80
- .control-group.success .select2-container-multi.select2-container-active .select2-choices {
81
- border: 1px solid #468847 !important;
82
- }
83
-
84
- .control-group.success .select2-container .select2-choice div {
85
- border-left: 1px solid #468847 !important;
86
- background: #DFF0D8 !important;
87
- }
@@ -1,615 +0,0 @@
1
- /*
2
- Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013
3
- */
4
- .select2-container {
5
- margin: 0;
6
- position: relative;
7
- display: inline-block;
8
- /* inline-block for ie7 */
9
- zoom: 1;
10
- *display: inline;
11
- vertical-align: middle;
12
- }
13
-
14
- .select2-container,
15
- .select2-drop,
16
- .select2-search,
17
- .select2-search input {
18
- /*
19
- Force border-box so that % widths fit the parent
20
- container without overlap because of margin/padding.
21
-
22
- More Info : http://www.quirksmode.org/css/box.html
23
- */
24
- -webkit-box-sizing: border-box; /* webkit */
25
- -moz-box-sizing: border-box; /* firefox */
26
- box-sizing: border-box; /* css3 */
27
- }
28
-
29
- .select2-container .select2-choice {
30
- display: block;
31
- height: 26px;
32
- padding: 0 0 0 8px;
33
- overflow: hidden;
34
- position: relative;
35
-
36
- border: 1px solid #aaa;
37
- white-space: nowrap;
38
- line-height: 26px;
39
- color: #444;
40
- text-decoration: none;
41
-
42
- border-radius: 4px;
43
-
44
- background-clip: padding-box;
45
-
46
- -webkit-touch-callout: none;
47
- -webkit-user-select: none;
48
- -moz-user-select: none;
49
- -ms-user-select: none;
50
- user-select: none;
51
-
52
- background-color: #fff;
53
- background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.5, #fff));
54
- background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 50%);
55
- background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 50%);
56
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#ffffff', endColorstr = '#eeeeee', GradientType = 0);
57
- background-image: linear-gradient(top, #fff 0%, #eee 50%);
58
- }
59
-
60
- .select2-container.select2-drop-above .select2-choice {
61
- border-bottom-color: #aaa;
62
-
63
- border-radius: 0 0 4px 4px;
64
-
65
- background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.9, #fff));
66
- background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 90%);
67
- background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 90%);
68
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
69
- background-image: linear-gradient(top, #eee 0%, #fff 90%);
70
- }
71
-
72
- .select2-container.select2-allowclear .select2-choice .select2-chosen {
73
- margin-right: 42px;
74
- }
75
-
76
- .select2-container .select2-choice > .select2-chosen {
77
- margin-right: 26px;
78
- display: block;
79
- overflow: hidden;
80
-
81
- white-space: nowrap;
82
-
83
- text-overflow: ellipsis;
84
- }
85
-
86
- .select2-container .select2-choice abbr {
87
- display: none;
88
- width: 12px;
89
- height: 12px;
90
- position: absolute;
91
- right: 24px;
92
- top: 8px;
93
-
94
- font-size: 1px;
95
- text-decoration: none;
96
-
97
- border: 0;
98
- background: url('../img/select2.png') right top no-repeat;
99
- cursor: pointer;
100
- outline: 0;
101
- }
102
-
103
- .select2-container.select2-allowclear .select2-choice abbr {
104
- display: inline-block;
105
- }
106
-
107
- .select2-container .select2-choice abbr:hover {
108
- background-position: right -11px;
109
- cursor: pointer;
110
- }
111
-
112
- .select2-drop-mask {
113
- border: 0;
114
- margin: 0;
115
- padding: 0;
116
- position: fixed;
117
- left: 0;
118
- top: 0;
119
- min-height: 100%;
120
- min-width: 100%;
121
- height: auto;
122
- width: auto;
123
- opacity: 0;
124
- z-index: 9998;
125
- /* styles required for IE to work */
126
- background-color: #fff;
127
- filter: alpha(opacity=0);
128
- }
129
-
130
- .select2-drop {
131
- width: 100%;
132
- margin-top: -1px;
133
- position: absolute;
134
- z-index: 9999;
135
- top: 100%;
136
-
137
- background: #fff;
138
- color: #000;
139
- border: 1px solid #aaa;
140
- border-top: 0;
141
-
142
- border-radius: 0 0 4px 4px;
143
-
144
- -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
145
- box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
146
- }
147
-
148
- .select2-drop-auto-width {
149
- border-top: 1px solid #aaa;
150
- width: auto;
151
- }
152
-
153
- .select2-drop-auto-width .select2-search {
154
- padding-top: 4px;
155
- }
156
-
157
- .select2-drop.select2-drop-above {
158
- margin-top: 1px;
159
- border-top: 1px solid #aaa;
160
- border-bottom: 0;
161
-
162
- border-radius: 4px 4px 0 0;
163
-
164
- -webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
165
- box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
166
- }
167
-
168
- .select2-drop-active {
169
- border: 1px solid #5897fb;
170
- border-top: none;
171
- }
172
-
173
- .select2-drop.select2-drop-above.select2-drop-active {
174
- border-top: 1px solid #5897fb;
175
- }
176
-
177
- .select2-container .select2-choice .select2-arrow {
178
- display: inline-block;
179
- width: 18px;
180
- height: 100%;
181
- position: absolute;
182
- right: 0;
183
- top: 0;
184
-
185
- border-left: 1px solid #aaa;
186
- border-radius: 0 4px 4px 0;
187
-
188
- background-clip: padding-box;
189
-
190
- background: #ccc;
191
- background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee));
192
- background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%);
193
- background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%);
194
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#cccccc', GradientType = 0);
195
- background-image: linear-gradient(top, #ccc 0%, #eee 60%);
196
- }
197
-
198
- .select2-container .select2-choice .select2-arrow b {
199
- display: block;
200
- width: 100%;
201
- height: 100%;
202
- background: url('../img/select2.png') no-repeat 0 1px;
203
- }
204
-
205
- .select2-search {
206
- display: inline-block;
207
- width: 100%;
208
- min-height: 26px;
209
- margin: 0;
210
- padding-left: 4px;
211
- padding-right: 4px;
212
-
213
- position: relative;
214
- z-index: 10000;
215
-
216
- white-space: nowrap;
217
- }
218
-
219
- .select2-search input {
220
- width: 100%;
221
- height: auto !important;
222
- min-height: 26px;
223
- padding: 4px 20px 4px 5px;
224
- margin: 0;
225
-
226
- outline: 0;
227
- font-family: sans-serif;
228
- font-size: 1em;
229
-
230
- border: 1px solid #aaa;
231
- border-radius: 0;
232
-
233
- -webkit-box-shadow: none;
234
- box-shadow: none;
235
-
236
- background: #fff url('../img/select2.png') no-repeat 100% -22px;
237
- background: url('../img/select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));
238
- background: url('../img/select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);
239
- background: url('../img/select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);
240
- background: url('../img/select2.png') no-repeat 100% -22px, linear-gradient(top, #fff 85%, #eee 99%);
241
- }
242
-
243
- .select2-drop.select2-drop-above .select2-search input {
244
- margin-top: 4px;
245
- }
246
-
247
- .select2-search input.select2-active {
248
- background: #fff url('../img/select2-spinner.gif') no-repeat 100%;
249
- background: url('../img/select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));
250
- background: url('../img/select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);
251
- background: url('../img/select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);
252
- background: url('../img/select2-spinner.gif') no-repeat 100%, linear-gradient(top, #fff 85%, #eee 99%);
253
- }
254
-
255
- .select2-container-active .select2-choice,
256
- .select2-container-active .select2-choices {
257
- border: 1px solid #5897fb;
258
- outline: none;
259
-
260
- -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);
261
- box-shadow: 0 0 5px rgba(0, 0, 0, .3);
262
- }
263
-
264
- .select2-dropdown-open .select2-choice {
265
- border-bottom-color: transparent;
266
- -webkit-box-shadow: 0 1px 0 #fff inset;
267
- box-shadow: 0 1px 0 #fff inset;
268
-
269
- border-bottom-left-radius: 0;
270
- border-bottom-right-radius: 0;
271
-
272
- background-color: #eee;
273
- background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #fff), color-stop(0.5, #eee));
274
- background-image: -webkit-linear-gradient(center bottom, #fff 0%, #eee 50%);
275
- background-image: -moz-linear-gradient(center bottom, #fff 0%, #eee 50%);
276
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);
277
- background-image: linear-gradient(top, #fff 0%, #eee 50%);
278
- }
279
-
280
- .select2-dropdown-open.select2-drop-above .select2-choice,
281
- .select2-dropdown-open.select2-drop-above .select2-choices {
282
- border: 1px solid #5897fb;
283
- border-top-color: transparent;
284
-
285
- background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(0.5, #eee));
286
- background-image: -webkit-linear-gradient(center top, #fff 0%, #eee 50%);
287
- background-image: -moz-linear-gradient(center top, #fff 0%, #eee 50%);
288
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);
289
- background-image: linear-gradient(bottom, #fff 0%, #eee 50%);
290
- }
291
-
292
- .select2-dropdown-open .select2-choice .select2-arrow {
293
- background: transparent;
294
- border-left: none;
295
- filter: none;
296
- }
297
- .select2-dropdown-open .select2-choice .select2-arrow b {
298
- background-position: -18px 1px;
299
- }
300
-
301
- /* results */
302
- .select2-results {
303
- max-height: 200px;
304
- padding: 0 0 0 4px;
305
- margin: 4px 4px 4px 0;
306
- position: relative;
307
- overflow-x: hidden;
308
- overflow-y: auto;
309
- -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
310
- }
311
-
312
- .select2-results ul.select2-result-sub {
313
- margin: 0;
314
- padding-left: 0;
315
- }
316
-
317
- .select2-results ul.select2-result-sub > li .select2-result-label { padding-left: 20px }
318
- .select2-results ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 40px }
319
- .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 60px }
320
- .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 80px }
321
- .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 100px }
322
- .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 110px }
323
- .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 120px }
324
-
325
- .select2-results li {
326
- list-style: none;
327
- display: list-item;
328
- background-image: none;
329
- }
330
-
331
- .select2-results li.select2-result-with-children > .select2-result-label {
332
- font-weight: bold;
333
- }
334
-
335
- .select2-results .select2-result-label {
336
- padding: 3px 7px 4px;
337
- margin: 0;
338
- cursor: pointer;
339
-
340
- min-height: 1em;
341
-
342
- -webkit-touch-callout: none;
343
- -webkit-user-select: none;
344
- -moz-user-select: none;
345
- -ms-user-select: none;
346
- user-select: none;
347
- }
348
-
349
- .select2-results .select2-highlighted {
350
- background: #3875d7;
351
- color: #fff;
352
- }
353
-
354
- .select2-results li em {
355
- background: #feffde;
356
- font-style: normal;
357
- }
358
-
359
- .select2-results .select2-highlighted em {
360
- background: transparent;
361
- }
362
-
363
- .select2-results .select2-highlighted ul {
364
- background: #fff;
365
- color: #000;
366
- }
367
-
368
-
369
- .select2-results .select2-no-results,
370
- .select2-results .select2-searching,
371
- .select2-results .select2-selection-limit {
372
- background: #f4f4f4;
373
- display: list-item;
374
- }
375
-
376
- /*
377
- disabled look for disabled choices in the results dropdown
378
- */
379
- .select2-results .select2-disabled.select2-highlighted {
380
- color: #666;
381
- background: #f4f4f4;
382
- display: list-item;
383
- cursor: default;
384
- }
385
- .select2-results .select2-disabled {
386
- background: #f4f4f4;
387
- display: list-item;
388
- cursor: default;
389
- }
390
-
391
- .select2-results .select2-selected {
392
- display: none;
393
- }
394
-
395
- .select2-more-results.select2-active {
396
- background: #f4f4f4 url('../img/select2-spinner.gif') no-repeat 100%;
397
- }
398
-
399
- .select2-more-results {
400
- background: #f4f4f4;
401
- display: list-item;
402
- }
403
-
404
- /* disabled styles */
405
-
406
- .select2-container.select2-container-disabled .select2-choice {
407
- background-color: #f4f4f4;
408
- background-image: none;
409
- border: 1px solid #ddd;
410
- cursor: default;
411
- }
412
-
413
- .select2-container.select2-container-disabled .select2-choice .select2-arrow {
414
- background-color: #f4f4f4;
415
- background-image: none;
416
- border-left: 0;
417
- }
418
-
419
- .select2-container.select2-container-disabled .select2-choice abbr {
420
- display: none;
421
- }
422
-
423
-
424
- /* multiselect */
425
-
426
- .select2-container-multi .select2-choices {
427
- height: auto !important;
428
- height: 1%;
429
- margin: 0;
430
- padding: 0;
431
- position: relative;
432
-
433
- border: 1px solid #aaa;
434
- cursor: text;
435
- overflow: hidden;
436
-
437
- background-color: #fff;
438
- background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eee), color-stop(15%, #fff));
439
- background-image: -webkit-linear-gradient(top, #eee 1%, #fff 15%);
440
- background-image: -moz-linear-gradient(top, #eee 1%, #fff 15%);
441
- background-image: linear-gradient(top, #eee 1%, #fff 15%);
442
- }
443
-
444
- .select2-locked {
445
- padding: 3px 5px 3px 5px !important;
446
- }
447
-
448
- .select2-container-multi .select2-choices {
449
- min-height: 26px;
450
- }
451
-
452
- .select2-container-multi.select2-container-active .select2-choices {
453
- border: 1px solid #5897fb;
454
- outline: none;
455
-
456
- -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);
457
- box-shadow: 0 0 5px rgba(0, 0, 0, .3);
458
- }
459
- .select2-container-multi .select2-choices li {
460
- float: left;
461
- list-style: none;
462
- }
463
- .select2-container-multi .select2-choices .select2-search-field {
464
- margin: 0;
465
- padding: 0;
466
- white-space: nowrap;
467
- }
468
-
469
- .select2-container-multi .select2-choices .select2-search-field input {
470
- padding: 5px;
471
- margin: 1px 0;
472
-
473
- font-family: sans-serif;
474
- font-size: 100%;
475
- color: #666;
476
- outline: 0;
477
- border: 0;
478
- -webkit-box-shadow: none;
479
- box-shadow: none;
480
- background: transparent !important;
481
- }
482
-
483
- .select2-container-multi .select2-choices .select2-search-field input.select2-active {
484
- background: #fff url('../img/select2-spinner.gif') no-repeat 100% !important;
485
- }
486
-
487
- .select2-default {
488
- color: #999 !important;
489
- }
490
-
491
- .select2-container-multi .select2-choices .select2-search-choice {
492
- padding: 3px 5px 3px 18px;
493
- margin: 3px 0 3px 5px;
494
- position: relative;
495
-
496
- line-height: 13px;
497
- color: #333;
498
- cursor: default;
499
- border: 1px solid #aaaaaa;
500
-
501
- border-radius: 3px;
502
-
503
- -webkit-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);
504
- box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);
505
-
506
- background-clip: padding-box;
507
-
508
- -webkit-touch-callout: none;
509
- -webkit-user-select: none;
510
- -moz-user-select: none;
511
- -ms-user-select: none;
512
- user-select: none;
513
-
514
- background-color: #e4e4e4;
515
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#f4f4f4', GradientType=0);
516
- background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eee));
517
- background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
518
- background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
519
- background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
520
- }
521
- .select2-container-multi .select2-choices .select2-search-choice .select2-chosen {
522
- cursor: default;
523
- }
524
- .select2-container-multi .select2-choices .select2-search-choice-focus {
525
- background: #d4d4d4;
526
- }
527
-
528
- .select2-search-choice-close {
529
- display: block;
530
- width: 12px;
531
- height: 13px;
532
- position: absolute;
533
- right: 3px;
534
- top: 4px;
535
-
536
- font-size: 1px;
537
- outline: none;
538
- background: url('../img/select2.png') right top no-repeat;
539
- }
540
-
541
- .select2-container-multi .select2-search-choice-close {
542
- left: 3px;
543
- }
544
-
545
- .select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover {
546
- background-position: right -11px;
547
- }
548
- .select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close {
549
- background-position: right -11px;
550
- }
551
-
552
- /* disabled styles */
553
- .select2-container-multi.select2-container-disabled .select2-choices {
554
- background-color: #f4f4f4;
555
- background-image: none;
556
- border: 1px solid #ddd;
557
- cursor: default;
558
- }
559
-
560
- .select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice {
561
- padding: 3px 5px 3px 5px;
562
- border: 1px solid #ddd;
563
- background-image: none;
564
- background-color: #f4f4f4;
565
- }
566
-
567
- .select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close { display: none;
568
- background: none;
569
- }
570
- /* end multiselect */
571
-
572
-
573
- .select2-result-selectable .select2-match,
574
- .select2-result-unselectable .select2-match {
575
- text-decoration: underline;
576
- }
577
-
578
- .select2-offscreen, .select2-offscreen:focus {
579
- clip: rect(0 0 0 0) !important;
580
- width: 1px !important;
581
- height: 1px !important;
582
- border: 0 !important;
583
- margin: 0 !important;
584
- padding: 0 !important;
585
- overflow: hidden !important;
586
- position: absolute !important;
587
- outline: 0 !important;
588
- left: 0px !important;
589
- top: 0px !important;
590
- }
591
-
592
- .select2-display-none {
593
- display: none;
594
- }
595
-
596
- .select2-measure-scrollbar {
597
- position: absolute;
598
- top: -10000px;
599
- left: -10000px;
600
- width: 100px;
601
- height: 100px;
602
- overflow: scroll;
603
- }
604
- /* Retina-ize icons */
605
-
606
- @media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi) {
607
- .select2-search input, .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice .select2-arrow b {
608
- background-image: url('../img/select2x2.png') !important;
609
- background-repeat: no-repeat !important;
610
- background-size: 60px 40px !important;
611
- }
612
- .select2-search input {
613
- background-position: 100% -21px !important;
614
- }
615
- }