flapjack 1.6.0 → 2.0.0b1

Sign up to get free protection for your applications and to get access to all the features.
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
- }