flapjack 1.6.0 → 2.0.0b1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -6
- data/.gitmodules +1 -1
- data/.rspec +1 -1
- data/.ruby-version +1 -1
- data/.travis.yml +12 -13
- data/CHANGELOG.md +2 -9
- data/CONTRIBUTING.md +7 -2
- data/Gemfile +4 -13
- data/LICENCE +1 -0
- data/README.md +8 -2
- data/Rakefile +2 -2
- data/bin/flapjack +3 -12
- data/build.sh +4 -2
- data/etc/flapjack_config.toml.example +273 -0
- data/features/ack_after_sched_maint.feature +18 -21
- data/features/cli.feature +11 -71
- data/features/cli_flapjack-feed-events.feature +14 -15
- data/features/cli_flapjack-nagios-receiver.feature +12 -41
- data/features/cli_flapper.feature +12 -41
- data/features/cli_purge.feature +5 -6
- data/features/cli_receive-events.feature +6 -7
- data/features/cli_simulate-failed-check.feature +5 -6
- data/features/events.feature +206 -181
- data/features/events_check_names.feature +4 -7
- data/features/notification_rules.feature +144 -223
- data/features/notifications.feature +65 -57
- data/features/rollup.feature +45 -47
- data/features/steps/cli_steps.rb +4 -5
- data/features/steps/events_steps.rb +163 -373
- data/features/steps/notifications_steps.rb +408 -264
- data/features/steps/packaging-lintian_steps.rb +0 -4
- data/features/steps/time_travel_steps.rb +0 -26
- data/features/support/daemons.rb +6 -31
- data/features/support/env.rb +65 -74
- data/flapjack.gemspec +22 -24
- data/lib/flapjack.rb +14 -7
- data/lib/flapjack/cli/flapper.rb +74 -173
- data/lib/flapjack/cli/maintenance.rb +278 -109
- data/lib/flapjack/cli/migrate.rb +950 -0
- data/lib/flapjack/cli/purge.rb +19 -22
- data/lib/flapjack/cli/receiver.rb +150 -326
- data/lib/flapjack/cli/server.rb +8 -235
- data/lib/flapjack/cli/simulate.rb +42 -57
- data/lib/flapjack/configuration.rb +51 -37
- data/lib/flapjack/coordinator.rb +138 -129
- data/lib/flapjack/data/acknowledgement.rb +177 -0
- data/lib/flapjack/data/alert.rb +97 -158
- data/lib/flapjack/data/check.rb +611 -0
- data/lib/flapjack/data/condition.rb +70 -0
- data/lib/flapjack/data/contact.rb +226 -456
- data/lib/flapjack/data/event.rb +96 -184
- data/lib/flapjack/data/extensions/associations.rb +59 -0
- data/lib/flapjack/data/extensions/short_name.rb +25 -0
- data/lib/flapjack/data/medium.rb +428 -0
- data/lib/flapjack/data/metrics.rb +194 -0
- data/lib/flapjack/data/notification.rb +22 -281
- data/lib/flapjack/data/rule.rb +473 -0
- data/lib/flapjack/data/scheduled_maintenance.rb +244 -0
- data/lib/flapjack/data/state.rb +221 -0
- data/lib/flapjack/data/statistic.rb +112 -0
- data/lib/flapjack/data/tag.rb +277 -0
- data/lib/flapjack/data/test_notification.rb +182 -0
- data/lib/flapjack/data/unscheduled_maintenance.rb +159 -0
- data/lib/flapjack/data/validators/id_validator.rb +20 -0
- data/lib/flapjack/exceptions.rb +6 -0
- data/lib/flapjack/filters/acknowledgement.rb +23 -16
- data/lib/flapjack/filters/base.rb +0 -5
- data/lib/flapjack/filters/delays.rb +53 -43
- data/lib/flapjack/filters/ok.rb +23 -14
- data/lib/flapjack/filters/scheduled_maintenance.rb +3 -3
- data/lib/flapjack/filters/unscheduled_maintenance.rb +12 -3
- data/lib/flapjack/gateways/aws_sns.rb +65 -49
- data/lib/flapjack/gateways/aws_sns/alert.text.erb +2 -2
- data/lib/flapjack/gateways/aws_sns/alert_subject.text.erb +2 -2
- data/lib/flapjack/gateways/aws_sns/rollup_subject.text.erb +1 -1
- data/lib/flapjack/gateways/email.rb +107 -90
- data/lib/flapjack/gateways/email/alert.html.erb +19 -18
- data/lib/flapjack/gateways/email/alert.text.erb +20 -14
- data/lib/flapjack/gateways/email/alert_subject.text.erb +2 -1
- data/lib/flapjack/gateways/email/rollup.html.erb +14 -13
- data/lib/flapjack/gateways/email/rollup.text.erb +13 -10
- data/lib/flapjack/gateways/jabber.rb +679 -671
- data/lib/flapjack/gateways/jabber/alert.text.erb +9 -6
- data/lib/flapjack/gateways/jsonapi.rb +164 -350
- data/lib/flapjack/gateways/jsonapi/data/join_descriptor.rb +44 -0
- data/lib/flapjack/gateways/jsonapi/data/method_descriptor.rb +21 -0
- data/lib/flapjack/gateways/jsonapi/helpers/headers.rb +63 -0
- data/lib/flapjack/gateways/jsonapi/helpers/miscellaneous.rb +136 -0
- data/lib/flapjack/gateways/jsonapi/helpers/resources.rb +227 -0
- data/lib/flapjack/gateways/jsonapi/helpers/serialiser.rb +313 -0
- data/lib/flapjack/gateways/jsonapi/helpers/swagger_docs.rb +322 -0
- data/lib/flapjack/gateways/jsonapi/methods/association_delete.rb +115 -0
- data/lib/flapjack/gateways/jsonapi/methods/association_get.rb +288 -0
- data/lib/flapjack/gateways/jsonapi/methods/association_patch.rb +178 -0
- data/lib/flapjack/gateways/jsonapi/methods/association_post.rb +116 -0
- data/lib/flapjack/gateways/jsonapi/methods/metrics.rb +71 -0
- data/lib/flapjack/gateways/jsonapi/methods/resource_delete.rb +119 -0
- data/lib/flapjack/gateways/jsonapi/methods/resource_get.rb +186 -0
- data/lib/flapjack/gateways/jsonapi/methods/resource_patch.rb +239 -0
- data/lib/flapjack/gateways/jsonapi/methods/resource_post.rb +197 -0
- data/lib/flapjack/gateways/jsonapi/middleware/array_param_fixer.rb +27 -0
- data/lib/flapjack/gateways/jsonapi/{rack → middleware}/json_params_parser.rb +7 -6
- data/lib/flapjack/gateways/jsonapi/middleware/request_timestamp.rb +18 -0
- data/lib/flapjack/gateways/oobetet.rb +222 -170
- data/lib/flapjack/gateways/pager_duty.rb +388 -0
- data/lib/flapjack/gateways/pager_duty/alert.text.erb +13 -0
- data/lib/flapjack/gateways/slack.rb +56 -48
- data/lib/flapjack/gateways/slack/alert.text.erb +1 -1
- data/lib/flapjack/gateways/slack/rollup.text.erb +1 -1
- data/lib/flapjack/gateways/sms_aspsms.rb +155 -0
- data/lib/flapjack/gateways/sms_aspsms/alert.text.erb +7 -0
- data/lib/flapjack/gateways/sms_aspsms/rollup.text.erb +2 -0
- data/lib/flapjack/gateways/sms_messagenet.rb +77 -57
- data/lib/flapjack/gateways/sms_messagenet/alert.text.erb +3 -2
- data/lib/flapjack/gateways/sms_nexmo.rb +53 -51
- data/lib/flapjack/gateways/sms_nexmo/alert.text.erb +2 -2
- data/lib/flapjack/gateways/sms_nexmo/rollup.text.erb +1 -1
- data/lib/flapjack/gateways/sms_twilio.rb +79 -62
- data/lib/flapjack/gateways/sms_twilio/alert.text.erb +3 -2
- data/lib/flapjack/gateways/web.rb +437 -345
- data/lib/flapjack/gateways/web/middleware/request_timestamp.rb +18 -0
- data/lib/flapjack/gateways/web/public/css/bootstrap.css +3793 -4340
- data/lib/flapjack/gateways/web/public/css/bootstrap.css.map +1 -0
- data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.eot +0 -0
- data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.svg +273 -214
- data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.woff +0 -0
- data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.woff2 +0 -0
- data/lib/flapjack/gateways/web/public/js/bootstrap.js +1637 -1607
- data/lib/flapjack/gateways/web/public/js/self_stats.js +1 -2
- data/lib/flapjack/gateways/web/views/_pagination.html.erb +19 -0
- data/lib/flapjack/gateways/web/views/check.html.erb +159 -121
- data/lib/flapjack/gateways/web/views/checks.html.erb +82 -41
- data/lib/flapjack/gateways/web/views/contact.html.erb +59 -71
- data/lib/flapjack/gateways/web/views/contacts.html.erb +32 -8
- data/lib/flapjack/gateways/web/views/index.html.erb +2 -2
- data/lib/flapjack/gateways/web/views/{layout.erb → layout.html.erb} +7 -23
- data/lib/flapjack/gateways/web/views/self_stats.html.erb +32 -33
- data/lib/flapjack/gateways/web/views/tag.html.erb +32 -0
- data/lib/flapjack/gateways/web/views/tags.html.erb +51 -0
- data/lib/flapjack/logger.rb +34 -3
- data/lib/flapjack/notifier.rb +180 -112
- data/lib/flapjack/patches.rb +8 -63
- data/lib/flapjack/pikelet.rb +185 -143
- data/lib/flapjack/processor.rb +323 -191
- data/lib/flapjack/record_queue.rb +33 -0
- data/lib/flapjack/redis_proxy.rb +66 -0
- data/lib/flapjack/utility.rb +21 -15
- data/lib/flapjack/version.rb +2 -1
- data/libexec/httpbroker.go +218 -14
- data/libexec/oneoff.go +13 -10
- data/spec/lib/flapjack/configuration_spec.rb +286 -0
- data/spec/lib/flapjack/coordinator_spec.rb +103 -157
- data/spec/lib/flapjack/data/check_spec.rb +175 -0
- data/spec/lib/flapjack/data/contact_spec.rb +26 -349
- data/spec/lib/flapjack/data/event_spec.rb +76 -291
- data/spec/lib/flapjack/data/medium_spec.rb +19 -0
- data/spec/lib/flapjack/data/rule_spec.rb +43 -0
- data/spec/lib/flapjack/data/scheduled_maintenance_spec.rb +976 -0
- data/spec/lib/flapjack/data/unscheduled_maintenance_spec.rb +34 -0
- data/spec/lib/flapjack/gateways/aws_sns_spec.rb +111 -60
- data/spec/lib/flapjack/gateways/email_spec.rb +194 -161
- data/spec/lib/flapjack/gateways/jabber_spec.rb +961 -162
- data/spec/lib/flapjack/gateways/jsonapi/methods/check_links_spec.rb +155 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/checks_spec.rb +426 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/contact_links_spec.rb +217 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/contacts_spec.rb +425 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/events_spec.rb +271 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/media_spec.rb +257 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/medium_links_spec.rb +163 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/metrics_spec.rb +8 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/rule_links_spec.rb +212 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/rules_spec.rb +289 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/scheduled_maintenance_links_spec.rb +49 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/scheduled_maintenances_spec.rb +242 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/tag_links_spec.rb +274 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/tags_spec.rb +302 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/unscheduled_maintenance_links_spec.rb +49 -0
- data/spec/lib/flapjack/gateways/jsonapi/methods/unscheduled_maintenances_spec.rb +339 -0
- data/spec/lib/flapjack/gateways/jsonapi_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/oobetet_spec.rb +151 -79
- data/spec/lib/flapjack/gateways/pager_duty_spec.rb +353 -0
- data/spec/lib/flapjack/gateways/slack_spec.rb +53 -53
- data/spec/lib/flapjack/gateways/sms_aspsms_spec.rb +106 -0
- data/spec/lib/flapjack/gateways/sms_messagenet_spec.rb +111 -54
- data/spec/lib/flapjack/gateways/sms_nexmo_spec.rb +50 -51
- data/spec/lib/flapjack/gateways/sms_twilio_spec.rb +108 -48
- data/spec/lib/flapjack/gateways/web_spec.rb +144 -216
- data/spec/lib/flapjack/notifier_spec.rb +132 -1
- data/spec/lib/flapjack/pikelet_spec.rb +111 -50
- data/spec/lib/flapjack/processor_spec.rb +210 -40
- data/spec/lib/flapjack/redis_proxy_spec.rb +45 -0
- data/spec/lib/flapjack/utility_spec.rb +11 -15
- data/spec/service_consumers/fixture_data.rb +547 -0
- data/spec/service_consumers/pact_helper.rb +21 -32
- data/spec/service_consumers/pacts/flapjack-diner_v2.0.json +4652 -0
- data/spec/service_consumers/provider_states_for_flapjack-diner.rb +279 -322
- data/spec/service_consumers/provider_support.rb +8 -0
- data/spec/spec_helper.rb +34 -44
- data/spec/support/erb_view_helper.rb +1 -1
- data/spec/support/factories.rb +58 -0
- data/spec/support/jsonapi_helper.rb +15 -26
- data/spec/support/mock_logger.rb +43 -0
- data/spec/support/xmpp_comparable.rb +24 -0
- data/src/flapjack/transport_test.go +30 -1
- data/tasks/dump_keys.rake +82 -0
- data/tasks/events.rake +7 -7
- data/tasks/support/flapjack_config_benchmark.toml +28 -0
- data/tasks/support/flapjack_config_benchmark.yaml +0 -2
- metadata +175 -222
- data/Guardfile +0 -14
- data/etc/flapjack_config.yaml.example +0 -477
- data/features/cli_flapjack-populator.feature +0 -90
- data/features/support/silent_system.rb +0 -4
- data/lib/flapjack/cli/import.rb +0 -108
- data/lib/flapjack/data/entity.rb +0 -652
- data/lib/flapjack/data/entity_check.rb +0 -1044
- data/lib/flapjack/data/message.rb +0 -56
- data/lib/flapjack/data/migration.rb +0 -234
- data/lib/flapjack/data/notification_rule.rb +0 -425
- data/lib/flapjack/data/semaphore.rb +0 -44
- data/lib/flapjack/data/tagged.rb +0 -48
- data/lib/flapjack/gateways/jsonapi/check_methods.rb +0 -206
- data/lib/flapjack/gateways/jsonapi/check_presenter.rb +0 -221
- data/lib/flapjack/gateways/jsonapi/contact_methods.rb +0 -186
- data/lib/flapjack/gateways/jsonapi/entity_methods.rb +0 -223
- data/lib/flapjack/gateways/jsonapi/medium_methods.rb +0 -185
- data/lib/flapjack/gateways/jsonapi/metrics_methods.rb +0 -132
- data/lib/flapjack/gateways/jsonapi/notification_rule_methods.rb +0 -141
- data/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb +0 -139
- data/lib/flapjack/gateways/jsonapi/report_methods.rb +0 -146
- data/lib/flapjack/gateways/pagerduty.rb +0 -318
- data/lib/flapjack/gateways/pagerduty/alert.text.erb +0 -10
- data/lib/flapjack/gateways/web/public/css/select2-bootstrap.css +0 -87
- data/lib/flapjack/gateways/web/public/css/select2.css +0 -615
- data/lib/flapjack/gateways/web/public/css/tablesort.css +0 -67
- data/lib/flapjack/gateways/web/public/img/select2-spinner.gif +0 -0
- data/lib/flapjack/gateways/web/public/img/select2.png +0 -0
- data/lib/flapjack/gateways/web/public/img/select2x2.png +0 -0
- data/lib/flapjack/gateways/web/public/js/backbone.js +0 -1581
- data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +0 -322
- data/lib/flapjack/gateways/web/public/js/flapjack.js +0 -82
- data/lib/flapjack/gateways/web/public/js/jquery.tablesorter.js +0 -1640
- data/lib/flapjack/gateways/web/public/js/jquery.tablesorter.widgets.js +0 -1390
- data/lib/flapjack/gateways/web/public/js/modules/contact.js +0 -520
- data/lib/flapjack/gateways/web/public/js/modules/entity.js +0 -28
- data/lib/flapjack/gateways/web/public/js/modules/medium.js +0 -40
- data/lib/flapjack/gateways/web/public/js/select2.js +0 -3397
- data/lib/flapjack/gateways/web/public/js/tablesort.js +0 -44
- data/lib/flapjack/gateways/web/public/js/underscore.js +0 -1276
- data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +0 -173
- data/lib/flapjack/gateways/web/views/entities.html.erb +0 -30
- data/lib/flapjack/gateways/web/views/entity.html.erb +0 -51
- data/lib/flapjack/rack_logger.rb +0 -47
- data/lib/flapjack/redis_pool.rb +0 -42
- data/spec/lib/flapjack/data/entity_check_spec.rb +0 -1418
- data/spec/lib/flapjack/data/entity_spec.rb +0 -872
- data/spec/lib/flapjack/data/message_spec.rb +0 -30
- data/spec/lib/flapjack/data/migration_spec.rb +0 -104
- data/spec/lib/flapjack/data/notification_rule_spec.rb +0 -232
- data/spec/lib/flapjack/data/notification_spec.rb +0 -53
- data/spec/lib/flapjack/data/semaphore_spec.rb +0 -24
- data/spec/lib/flapjack/filters/acknowledgement_spec.rb +0 -6
- data/spec/lib/flapjack/filters/delays_spec.rb +0 -6
- data/spec/lib/flapjack/filters/ok_spec.rb +0 -6
- data/spec/lib/flapjack/filters/scheduled_maintenance_spec.rb +0 -6
- data/spec/lib/flapjack/filters/unscheduled_maintenance_spec.rb +0 -6
- data/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb +0 -315
- data/spec/lib/flapjack/gateways/jsonapi/check_presenter_spec.rb +0 -223
- data/spec/lib/flapjack/gateways/jsonapi/contact_methods_spec.rb +0 -131
- data/spec/lib/flapjack/gateways/jsonapi/entity_methods_spec.rb +0 -389
- data/spec/lib/flapjack/gateways/jsonapi/medium_methods_spec.rb +0 -231
- data/spec/lib/flapjack/gateways/jsonapi/notification_rule_methods_spec.rb +0 -169
- data/spec/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods_spec.rb +0 -114
- data/spec/lib/flapjack/gateways/jsonapi/report_methods_spec.rb +0 -590
- data/spec/lib/flapjack/gateways/pagerduty_spec.rb +0 -249
- data/spec/lib/flapjack/gateways/web/views/check.html.erb_spec.rb +0 -21
- data/spec/lib/flapjack/gateways/web/views/contact.html.erb_spec.rb +0 -24
- data/spec/lib/flapjack/gateways/web/views/index.html.erb_spec.rb +0 -16
- data/spec/lib/flapjack/redis_pool_spec.rb +0 -29
- data/spec/service_consumers/pacts/flapjack-diner_v1.0.json +0 -4702
- data/tasks/entities.rake +0 -151
- data/tasks/profile.rake +0 -282
- data/tmp/acknowledge.rb +0 -13
- data/tmp/create_config_yaml.rb +0 -16
- data/tmp/create_event_ok.rb +0 -30
- data/tmp/create_event_unknown.rb +0 -30
- data/tmp/create_events_failure.rb +0 -34
- data/tmp/create_events_ok.rb +0 -32
- data/tmp/create_events_ok_fail_ack_ok.rb +0 -53
- data/tmp/create_events_ok_failure.rb +0 -41
- data/tmp/create_events_ok_failure_ack.rb +0 -53
- data/tmp/dummy_contacts.json +0 -43
- data/tmp/dummy_entities.json +0 -37
- data/tmp/generate_nagios_test_hosts.rb +0 -16
- data/tmp/notification_rules.rb +0 -73
- data/tmp/parse_config_yaml.rb +0 -7
- data/tmp/redis_find_spurious_unknown_states.rb +0 -52
- data/tmp/test_json_post.rb +0 -19
- data/tmp/test_notification_rules_api.rb +0 -171
@@ -1,6 +1,6 @@
|
|
1
1
|
<% summary = @alert.summary -%>
|
2
|
-
<%= @alert.type_sentence_case %>: '<%= @alert.check %>'
|
2
|
+
<%= @alert.type_sentence_case %>: '<%= @alert.check.name %>' -%>
|
3
3
|
<% unless ['acknowledgement', 'test'].include?(@alert.notification_type) -%>
|
4
4
|
is <%= @alert.state_title_case -%>
|
5
5
|
<% end -%>
|
6
|
-
at <%= Time.at(@alert.time).strftime('%-d %b %H:%M') %><%= (summary.nil? || summary.empty?) ? '' : ", #{summary}" -%>
|
6
|
+
at <%= Time.at(@alert.time).strftime('%-d %b %H:%M') %><%= (summary.nil? || summary.empty?) ? '' : ", #{summary}" -%>
|
@@ -1,2 +1,2 @@
|
|
1
1
|
<%= @alert.type_sentence_case %>: <%= @alert.rollup_states_summary -%>
|
2
|
-
(<%= @alert.rollup_states_detail_text(:max_checks_per_state => 3) -%>)
|
2
|
+
(<%= @alert.rollup_states_detail_text(:max_checks_per_state => 3) -%>)
|
@@ -1,13 +1,18 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require '
|
4
|
-
require '
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
5
|
+
require 'uri/https'
|
6
|
+
|
5
7
|
require 'active_support/inflector'
|
6
8
|
|
7
|
-
require 'flapjack/
|
9
|
+
require 'flapjack/redis_proxy'
|
10
|
+
require 'flapjack/record_queue'
|
11
|
+
require 'flapjack/utility'
|
12
|
+
require 'flapjack/exceptions'
|
8
13
|
|
9
14
|
require 'flapjack/data/alert'
|
10
|
-
require 'flapjack/
|
15
|
+
require 'flapjack/data/check'
|
11
16
|
|
12
17
|
module Flapjack
|
13
18
|
module Gateways
|
@@ -19,83 +24,86 @@ module Flapjack
|
|
19
24
|
# --data-urlencode 'Body=Sausage' \
|
20
25
|
# -u [AccountSid]:[AuthToken]
|
21
26
|
|
27
|
+
TWILIO_DEFAULT_HOST = 'api.twilio.com'
|
28
|
+
|
29
|
+
attr_accessor :sent
|
30
|
+
|
22
31
|
include Flapjack::Utility
|
23
32
|
|
24
33
|
def initialize(opts = {})
|
34
|
+
@lock = opts[:lock]
|
35
|
+
|
25
36
|
@config = opts[:config]
|
26
|
-
@logger = opts[:logger]
|
27
|
-
@redis_config = opts[:redis_config] || {}
|
28
|
-
@redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 1, :logger => @logger)
|
29
37
|
|
30
|
-
|
31
|
-
@
|
38
|
+
# TODO support for config reloading
|
39
|
+
@queue = Flapjack::RecordQueue.new(@config['queue'] || 'sms_twilio_notifications',
|
40
|
+
Flapjack::Data::Alert)
|
32
41
|
|
33
42
|
@sent = 0
|
34
|
-
end
|
35
|
-
|
36
|
-
def stop
|
37
|
-
@logger.info("stopping")
|
38
|
-
@should_quit = true
|
39
43
|
|
40
|
-
|
41
|
-
"redis://#{@redis_config[:host] || '127.0.0.1'}:#{@redis_config[:port] || '6379'}/#{@redis_config[:db] || '0'}"
|
42
|
-
shutdown_redis = EM::Hiredis.connect(redis_uri)
|
43
|
-
shutdown_redis.rpush(@config['queue'], Flapjack.dump_json('notification_type' => 'shutdown'))
|
44
|
+
Flapjack.logger.debug("new sms_twilio gateway pikelet with the following options: #{@config.inspect}")
|
44
45
|
end
|
45
46
|
|
46
47
|
def start
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
@
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
@
|
56
|
-
e.backtrace.join("\n")
|
48
|
+
begin
|
49
|
+
Zermelo.redis = Flapjack.redis
|
50
|
+
|
51
|
+
loop do
|
52
|
+
@lock.synchronize do
|
53
|
+
@queue.foreach {|alert| handle_alert(alert) }
|
54
|
+
end
|
55
|
+
|
56
|
+
@queue.wait
|
57
57
|
end
|
58
|
+
ensure
|
59
|
+
Flapjack.redis.quit
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
61
|
-
def
|
63
|
+
def stop_type
|
64
|
+
:exception
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def handle_alert(alert)
|
62
70
|
account_sid = @config["account_sid"]
|
63
|
-
auth_token
|
64
|
-
from
|
65
|
-
|
71
|
+
auth_token = @config["auth_token"]
|
72
|
+
from = @config["from"]
|
73
|
+
|
74
|
+
endpoint_host = @config["endpoint_host"] || TWILIO_DEFAULT_HOST
|
75
|
+
endpoint_path = @config["endpoint_path"] || "/2010-04-01/Accounts/#{account_sid}/Messages.json"
|
66
76
|
|
67
|
-
address
|
68
|
-
notification_id = alert.
|
69
|
-
message_type
|
77
|
+
address = alert.medium.address
|
78
|
+
notification_id = alert.id
|
79
|
+
message_type = alert.rollup ? 'rollup' : 'alert'
|
70
80
|
|
81
|
+
sms_dir = File.join(File.dirname(__FILE__), 'sms_twilio')
|
71
82
|
sms_template_erb, sms_template =
|
72
|
-
load_template(@config['templates'], message_type, 'text',
|
73
|
-
File.join(File.dirname(__FILE__), 'sms_twilio'))
|
83
|
+
load_template(@config['templates'], message_type, 'text', sms_dir)
|
74
84
|
|
75
|
-
@alert
|
76
|
-
bnd
|
85
|
+
@alert = alert
|
86
|
+
bnd = binding
|
77
87
|
|
78
88
|
begin
|
79
89
|
message = sms_template_erb.result(bnd).chomp
|
80
90
|
rescue => e
|
81
|
-
|
91
|
+
Flapjack.logger.error "Error while executing the ERB for an sms: " +
|
82
92
|
"ERB being executed: #{sms_template}"
|
83
93
|
raise
|
84
94
|
end
|
85
95
|
|
86
96
|
if @config.nil? || (@config.respond_to?(:empty?) && @config.empty?)
|
87
|
-
|
97
|
+
Flapjack.logger.error "sms twilio config is missing"
|
88
98
|
return
|
89
99
|
end
|
90
100
|
|
91
101
|
errors = []
|
92
102
|
|
93
|
-
safe_message = truncate(message, 159)
|
94
|
-
|
95
103
|
[[account_sid, "Twilio account_sid is missing"],
|
96
104
|
[auth_token, "Twilio auth_token is missing"],
|
97
|
-
[from,
|
98
|
-
[address,
|
105
|
+
[from, "SMS from address is missing"],
|
106
|
+
[address, "SMS address is missing"],
|
99
107
|
[notification_id, "Notification id is missing"]].each do |val_err|
|
100
108
|
|
101
109
|
next unless val_err.first.nil? || (val_err.first.respond_to?(:empty?) && val_err.first.empty?)
|
@@ -103,33 +111,42 @@ module Flapjack
|
|
103
111
|
end
|
104
112
|
|
105
113
|
unless errors.empty?
|
106
|
-
errors.each {|err|
|
114
|
+
errors.each {|err| Flapjack.logger.error err }
|
107
115
|
return
|
108
116
|
end
|
109
117
|
|
110
|
-
body_data = {
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
118
|
+
body_data = {
|
119
|
+
'To' => address,
|
120
|
+
'From' => from,
|
121
|
+
'Body' => truncate(message, 159)
|
122
|
+
}
|
123
|
+
|
124
|
+
Flapjack.logger.debug "body_data: #{body_data.inspect}"
|
125
|
+
Flapjack.logger.debug "authorization: [#{account_sid}, #{auth_token[0..2]}...#{auth_token[-3..-1]}]"
|
126
|
+
|
127
|
+
req = Net::HTTP::Post.new(endpoint_path)
|
128
|
+
req.set_form_data(body_data)
|
129
|
+
req['Authorization'] = [account_sid, auth_token]
|
130
|
+
|
131
|
+
http_response = Net::HTTP.start(endpoint_host, 443, :use_ssl => true) do |http|
|
132
|
+
http.request(req)
|
133
|
+
end
|
115
134
|
|
116
|
-
|
135
|
+
Flapjack.logger.debug "server response: #{http_response.inspect}"
|
117
136
|
|
118
|
-
|
137
|
+
status = http_response.code
|
119
138
|
|
120
|
-
|
121
|
-
if (status >= 200) && (status <= 206)
|
139
|
+
if (status.to_i >= 200) && (status.to_i <= 206)
|
122
140
|
@sent += 1
|
123
|
-
|
124
|
-
|
125
|
-
"notification_id: #{notification_id}"
|
141
|
+
Flapjack.logger.info "Sent SMS via Twilio, response status is #{status}, " +
|
142
|
+
"alert id: #{alert.id}"
|
126
143
|
else
|
127
|
-
|
128
|
-
"
|
144
|
+
Flapjack.logger.error "Failed to send SMS via Twilio, response status is #{status}, " +
|
145
|
+
"alert id: #{alert.id}"
|
129
146
|
end
|
130
147
|
rescue => e
|
131
|
-
|
132
|
-
|
148
|
+
Flapjack.logger.error "Error generating or delivering twilio sms to #{alert.medium.address}: #{e.class}: #{e.message}"
|
149
|
+
Flapjack.logger.error e.backtrace.join("\n")
|
133
150
|
raise
|
134
151
|
end
|
135
152
|
|
@@ -1,6 +1,7 @@
|
|
1
|
+
<% check = @alert.check -%>
|
1
2
|
<% summary = @alert.summary -%>
|
2
|
-
<%= @alert.type_sentence_case %>:
|
3
|
-
<% unless ['acknowledgement', 'test'].include?(@alert.
|
3
|
+
<%= @alert.type_sentence_case %>: <%= "'#{check.name}'" -%>
|
4
|
+
<% unless ['acknowledgement', 'test'].include?(@alert.type) -%>
|
4
5
|
is <%= @alert.state_title_case -%>
|
5
6
|
<% end -%>
|
6
7
|
at <%= Time.at(@alert.time).strftime('%-d %b %H:%M') %><%= (summary.nil? || summary.empty?) ? '' : ", #{summary}" -%>
|
@@ -3,16 +3,13 @@
|
|
3
3
|
require 'chronic'
|
4
4
|
require 'chronic_duration'
|
5
5
|
require 'sinatra/base'
|
6
|
-
require 'erb'
|
7
|
-
require 'rack/fiber_pool'
|
8
|
-
require 'json'
|
6
|
+
require 'tilt/erb'
|
9
7
|
require 'uri'
|
10
8
|
|
11
|
-
require 'flapjack/
|
9
|
+
require 'flapjack/gateways/web/middleware/request_timestamp'
|
10
|
+
|
11
|
+
require 'flapjack-diner'
|
12
12
|
|
13
|
-
require 'flapjack/data/contact'
|
14
|
-
require 'flapjack/data/entity_check'
|
15
|
-
require 'flapjack/redis_pool'
|
16
13
|
require 'flapjack/utility'
|
17
14
|
|
18
15
|
module Flapjack
|
@@ -21,67 +18,66 @@ module Flapjack
|
|
21
18
|
|
22
19
|
class Web < Sinatra::Base
|
23
20
|
|
24
|
-
|
25
|
-
if @config['show_exceptions'].is_a?(TrueClass)
|
26
|
-
# ensure the sinatra error page shows properly
|
27
|
-
request = Sinatra::Request.new(env)
|
28
|
-
printer = Sinatra::ShowExceptions.new(proc{ raise e })
|
29
|
-
s, h, b = printer.call(env)
|
30
|
-
[s, h, b]
|
31
|
-
else
|
32
|
-
@logger.error e.message
|
33
|
-
@logger.error e.backtrace.join("\n")
|
34
|
-
[503, {}, ""]
|
35
|
-
end
|
36
|
-
end
|
37
|
-
use Rack::FiberPool, :size => 25, :rescue_exception => rescue_exception
|
21
|
+
set :root, File.dirname(__FILE__)
|
38
22
|
|
23
|
+
use Flapjack::Gateways::Web::Middleware::RequestTimestamp
|
39
24
|
use Rack::MethodOverride
|
40
25
|
|
26
|
+
set :sessions, :true
|
27
|
+
|
28
|
+
set :raise_errors, false
|
29
|
+
set :protection, except: :path_traversal
|
30
|
+
|
31
|
+
set :views, settings.root + '/web/views'
|
32
|
+
set :public_folder, settings.root + '/web/public'
|
33
|
+
|
34
|
+
set :erb, :layout => 'layout.html'.to_sym
|
35
|
+
|
41
36
|
class << self
|
42
37
|
def start
|
43
|
-
|
38
|
+
Flapjack.logger.info "starting web - class"
|
44
39
|
|
45
|
-
|
40
|
+
set :show_exceptions, false
|
41
|
+
@show_exceptions = Sinatra::ShowExceptions.new(self)
|
46
42
|
|
47
|
-
if
|
48
|
-
|
49
|
-
|
50
|
-
puts "Exiting!"
|
51
|
-
exit
|
43
|
+
if access_log = (@config && @config['access_log'])
|
44
|
+
unless File.directory?(File.dirname(access_log))
|
45
|
+
raise "Parent directory for log file #{access_log} doesn't exist"
|
52
46
|
end
|
53
47
|
|
54
|
-
|
55
|
-
use Flapjack::CommonLogger, access_logger
|
48
|
+
use Rack::CommonLogger, ::Logger.new(@config['access_log'])
|
56
49
|
end
|
57
50
|
|
51
|
+
# session's only used for error message display, so
|
52
|
+
session_secret = @config['session_secret']
|
53
|
+
|
54
|
+
use Rack::Session::Cookie, :key => 'flapjack.session',
|
55
|
+
:path => '/',
|
56
|
+
:secret => session_secret || SecureRandom.hex(64)
|
57
|
+
|
58
58
|
@api_url = @config['api_url']
|
59
|
-
if @api_url
|
60
|
-
|
61
|
-
@logger.error "api_url is not a valid http or https URI (#{@api_url}), discarding"
|
62
|
-
@api_url = nil
|
63
|
-
end
|
64
|
-
unless @api_url.match(/^.*\/$/)
|
65
|
-
@logger.info "api_url must end with a trailing '/', setting to '#{@api_url}/'"
|
66
|
-
@api_url = "#{@api_url}/"
|
67
|
-
end
|
59
|
+
if @api_url.nil?
|
60
|
+
raise "'api_url' config must contain a Flapjack API instance address"
|
68
61
|
end
|
69
62
|
|
70
|
-
|
71
|
-
@
|
63
|
+
uri = begin
|
64
|
+
URI(@api_url)
|
65
|
+
rescue URI::InvalidURIError
|
66
|
+
# TODO should we just log and re-raise the exception?
|
67
|
+
raise "'api_url' is not a valid URI (#{@api_url})"
|
72
68
|
end
|
73
69
|
|
74
|
-
|
75
|
-
|
76
|
-
@logger.info "base_url is not configured, setting to '/'"
|
77
|
-
@base_url = '/'
|
70
|
+
unless ['http', 'https'].include?(uri.scheme)
|
71
|
+
raise "'api_url' is not a valid http or https URI (#{@api_url})"
|
78
72
|
end
|
79
|
-
|
80
|
-
|
81
|
-
@
|
82
|
-
@base_url = "#{@base_url}/"
|
73
|
+
unless @api_url.match(/^.*\/$/)
|
74
|
+
Flapjack.logger.info "api_url must end with a trailing '/', setting to '#{@api_url}/'"
|
75
|
+
@api_url = "#{@api_url}/"
|
83
76
|
end
|
84
77
|
|
78
|
+
Flapjack::Diner.base_uri(@api_url)
|
79
|
+
Flapjack::Diner.logger = Flapjack.logger
|
80
|
+
|
85
81
|
# constants won't be exposed to eRb scope
|
86
82
|
@default_logo_url = "img/flapjack-2013-notext-transparent-300-300.png"
|
87
83
|
@logo_image_file = nil
|
@@ -92,21 +88,17 @@ module Flapjack
|
|
92
88
|
@logo_image_file = logo_image_path
|
93
89
|
@logo_image_ext = File.extname(logo_image_path)
|
94
90
|
else
|
95
|
-
|
91
|
+
Flapjack.logger.error "logo_image_path '#{logo_image_path}'' does not point to a valid file."
|
96
92
|
end
|
97
93
|
end
|
98
94
|
|
99
|
-
@auto_refresh = @config['auto_refresh'].respond_to?('to_i') &&
|
95
|
+
@auto_refresh = (@config['auto_refresh'].respond_to?('to_i') &&
|
96
|
+
(@config['auto_refresh'].to_i > 0)) ? @config['auto_refresh'].to_i : false
|
100
97
|
end
|
101
98
|
end
|
102
99
|
|
103
100
|
include Flapjack::Utility
|
104
101
|
|
105
|
-
set :protection, :except => :path_traversal
|
106
|
-
|
107
|
-
set :views, settings.root + '/web/views'
|
108
|
-
set :public_folder, settings.root + '/web/public'
|
109
|
-
|
110
102
|
helpers do
|
111
103
|
def h(text)
|
112
104
|
ERB::Util.h(text)
|
@@ -117,28 +109,29 @@ module Flapjack
|
|
117
109
|
end
|
118
110
|
|
119
111
|
def include_active?(path)
|
120
|
-
request.path == "/#{path}"
|
112
|
+
return '' unless request.path == "/#{path}"
|
113
|
+
" class='active'"
|
121
114
|
end
|
122
115
|
|
123
116
|
def charset_for_content_type(ct)
|
124
117
|
charset = Encoding.default_external
|
125
|
-
charset.nil? ? ct : "#{ct}; charset=#{charset}"
|
118
|
+
charset.nil? ? ct : "#{ct}; charset=#{charset.name}"
|
126
119
|
end
|
127
120
|
end
|
128
121
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
def logger
|
134
|
-
self.class.instance_variable_get('@logger')
|
122
|
+
['config'].each do |class_inst_var|
|
123
|
+
define_method(class_inst_var.to_sym) do
|
124
|
+
self.class.instance_variable_get("@#{class_inst_var}")
|
125
|
+
end
|
135
126
|
end
|
136
127
|
|
137
128
|
before do
|
138
129
|
content_type charset_for_content_type('text/html')
|
139
130
|
|
140
|
-
|
141
|
-
|
131
|
+
# needs to be done per-thread
|
132
|
+
Flapjack.configure_log('web', config['logger'])
|
133
|
+
|
134
|
+
@base_url = "#{request.base_url}/"
|
142
135
|
@default_logo_url = self.class.instance_variable_get('@default_logo_url')
|
143
136
|
@logo_image_file = self.class.instance_variable_get('@logo_image_file')
|
144
137
|
@logo_image_ext = self.class.instance_variable_get('@logo_image_ext')
|
@@ -146,14 +139,14 @@ module Flapjack
|
|
146
139
|
|
147
140
|
input = nil
|
148
141
|
query_string = (request.query_string.respond_to?(:length) &&
|
149
|
-
|
150
|
-
if logger.debug?
|
142
|
+
request.query_string.length > 0) ? "?#{request.query_string}" : ""
|
143
|
+
if Flapjack.logger.debug?
|
151
144
|
input = env['rack.input'].read
|
152
|
-
logger.debug("#{request.request_method} #{request.path_info}#{query_string} #{input}")
|
153
|
-
elsif logger.info?
|
145
|
+
Flapjack.logger.debug("#{request.request_method} #{request.path_info}#{query_string} #{input}")
|
146
|
+
elsif Flapjack.logger.info?
|
154
147
|
input = env['rack.input'].read
|
155
148
|
input_short = input.gsub(/\n/, '').gsub(/\s+/, ' ')
|
156
|
-
logger.info("#{request.request_method} #{request.path_info}#{query_string} #{input_short[0..80]}")
|
149
|
+
Flapjack.logger.info("#{request.request_method} #{request.path_info}#{query_string} #{input_short[0..80]}")
|
157
150
|
end
|
158
151
|
env['rack.input'].rewind unless input.nil?
|
159
152
|
end
|
@@ -161,366 +154,435 @@ module Flapjack
|
|
161
154
|
get '/img/branding.*' do
|
162
155
|
halt(404) unless @logo_image_file && params[:splat].first.eql?(@logo_image_ext[1..-1])
|
163
156
|
send_file(@logo_image_file)
|
164
|
-
|
157
|
+
end
|
165
158
|
|
166
159
|
get '/' do
|
167
|
-
|
168
|
-
entity_stats
|
160
|
+
@metrics = Flapjack::Diner.metrics
|
169
161
|
|
170
162
|
erb 'index.html'.to_sym
|
171
163
|
end
|
172
164
|
|
173
|
-
get '/
|
174
|
-
|
175
|
-
@adjective = ''
|
176
|
-
|
177
|
-
checks_by_entity = Flapjack::Data::EntityCheck.find_current_names_by_entity(:redis => redis)
|
178
|
-
@states = checks_by_entity.keys.inject({}) {|result, entity_name|
|
179
|
-
Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis, :create => true)
|
180
|
-
result[entity_name] = checks_by_entity[entity_name].sort.map {|check|
|
181
|
-
[check] + entity_check_state(entity_name, check)
|
182
|
-
}
|
183
|
-
result
|
184
|
-
}
|
185
|
-
@entities_sorted = checks_by_entity.keys.sort
|
165
|
+
get '/self_stats' do
|
166
|
+
@current_time = Time.now
|
186
167
|
|
187
|
-
|
188
|
-
end
|
168
|
+
@api_url = self.class.instance_variable_get('@api_url')
|
189
169
|
|
190
|
-
|
191
|
-
|
192
|
-
@adjective = 'failing'
|
170
|
+
@metrics = Flapjack::Diner.metrics
|
171
|
+
statistics = Flapjack::Diner.statistics
|
193
172
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
173
|
+
unless statistics.nil?
|
174
|
+
@executive_instances = statistics.each_with_object({}) do |stats, memo|
|
175
|
+
if 'global'.eql?(stats[:instance_name])
|
176
|
+
@global_stats = stats
|
177
|
+
next
|
178
|
+
end
|
179
|
+
boot_time = Time.parse(stats[:created_at])
|
180
|
+
uptime = @current_time - boot_time
|
181
|
+
uptime_string = ChronicDuration.output(uptime, :format => :short,
|
182
|
+
:keep_zero => true, :units => 2) || '0s'
|
202
183
|
|
203
|
-
|
204
|
-
|
184
|
+
event_counters = {}
|
185
|
+
event_rates = {}
|
205
186
|
|
206
|
-
|
207
|
-
|
208
|
-
self_stats
|
209
|
-
logger.debug "calculating entity_stats"
|
210
|
-
entity_stats
|
211
|
-
logger.debug "calculating check_stats"
|
212
|
-
check_stats
|
187
|
+
[:all_events, :ok_events, :failure_events, :action_events,
|
188
|
+
:invalid_events].each do |evt|
|
213
189
|
|
214
|
-
|
215
|
-
|
190
|
+
count = stats[evt]
|
191
|
+
event_counters[evt] = count
|
192
|
+
event_rates[evt] = (uptime > 0) ? (count.to_f / uptime).round : nil
|
193
|
+
end
|
216
194
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
'events_queued' => @events_queued,
|
223
|
-
'all_entities' => @count_current_entities,
|
224
|
-
'failing_entities' => @count_failing_entities,
|
225
|
-
'all_checks' => @count_current_checks,
|
226
|
-
'failing_checks' => @count_failing_checks,
|
227
|
-
'processed_events' => {
|
228
|
-
'all_time' => {
|
229
|
-
'total' => @event_counters['all'].to_i,
|
230
|
-
'ok' => @event_counters['ok'].to_i,
|
231
|
-
'failure' => @event_counters['failure'].to_i,
|
232
|
-
'action' => @event_counters['action'].to_i,
|
195
|
+
memo[stats[:instance_name]] = {
|
196
|
+
:uptime => uptime,
|
197
|
+
:uptime_string => uptime_string,
|
198
|
+
:event_counters => event_counters,
|
199
|
+
:event_rates => event_rates
|
233
200
|
}
|
234
|
-
|
235
|
-
|
236
|
-
'total_keys' => @dbsize,
|
237
|
-
'uptime' => @uptime_string,
|
238
|
-
'boottime' => @boot_time,
|
239
|
-
'current_time' => Time.now,
|
240
|
-
'executive_instances' => @executive_instances,
|
241
|
-
}
|
242
|
-
Flapjack.dump_json(json_data)
|
243
|
-
end
|
201
|
+
end
|
202
|
+
end
|
244
203
|
|
245
|
-
|
246
|
-
redirect '/entities'
|
204
|
+
erb 'self_stats.html'.to_sym
|
247
205
|
end
|
248
206
|
|
249
|
-
get '/
|
250
|
-
|
207
|
+
get '/tags' do
|
208
|
+
opts = {}
|
209
|
+
@name = params[:name]
|
210
|
+
opts.update(:name => @name) unless @name.nil? || @name.empty?
|
211
|
+
|
212
|
+
@tags = Flapjack::Diner.tags(:filter => opts,
|
213
|
+
:page => (params[:page] || 1))
|
251
214
|
|
252
|
-
|
253
|
-
|
215
|
+
unless @tags.nil? || @tags.empty?
|
216
|
+
@pagination = pagination_from_context(Flapjack::Diner.context)
|
217
|
+
unless @pagination.nil?
|
218
|
+
@links = create_pagination_links(@pagination[:page],
|
219
|
+
@pagination[:total_pages])
|
220
|
+
end
|
221
|
+
end
|
254
222
|
|
255
|
-
erb '
|
223
|
+
erb 'tags.html'.to_sym
|
256
224
|
end
|
257
225
|
|
258
|
-
get '/
|
259
|
-
|
260
|
-
@adjective = 'decommissioned'
|
261
|
-
@entities = Flapjack::Data::Entity.all(:enabled => false, :redis => redis)
|
226
|
+
get '/tags/:id' do
|
227
|
+
tag_id = params[:id]
|
262
228
|
|
263
|
-
|
264
|
-
|
229
|
+
@tag = Flapjack::Diner.tags(tag_id, :include => 'checks')
|
230
|
+
err(404, "Could not find tag '#{tag_id}'") if @tag.nil?
|
265
231
|
|
266
|
-
|
267
|
-
entity_stats
|
268
|
-
@adjective = 'failing'
|
269
|
-
@entities = Flapjack::Data::Entity.find_all_names_with_failing_checks(:redis => redis)
|
232
|
+
@checks = Flapjack::Diner.related(@tag, :checks)
|
270
233
|
|
271
|
-
erb '
|
234
|
+
erb 'tag.html'.to_sym
|
272
235
|
end
|
273
236
|
|
274
|
-
get '/
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
237
|
+
get '/checks' do
|
238
|
+
time = Time.now
|
239
|
+
|
240
|
+
opts = {}
|
241
|
+
|
242
|
+
@name = params[:name]
|
243
|
+
opts.update(:name => @name) unless @name.nil? || @name.empty?
|
244
|
+
|
245
|
+
@enabled = boolean_from_str(params[:enabled])
|
246
|
+
opts.update(:enabled => @enabled) unless @enabled.nil?
|
247
|
+
|
248
|
+
@failing = boolean_from_str(params[:failing])
|
249
|
+
opts.update(:failing => @failing) unless @failing.nil?
|
250
|
+
|
251
|
+
@checks = Flapjack::Diner.checks(:filter => opts,
|
252
|
+
:page => (params[:page] || 1),
|
253
|
+
:include => ['current_state', 'latest_notifications',
|
254
|
+
'current_scheduled_maintenances',
|
255
|
+
'current_unscheduled_maintenance'])
|
256
|
+
|
257
|
+
@states = {}
|
258
|
+
|
259
|
+
unless @checks.nil? || @checks.empty?
|
260
|
+
@pagination = pagination_from_context(Flapjack::Diner.context)
|
261
|
+
unless @pagination.nil?
|
262
|
+
@links = create_pagination_links(@pagination[:page],
|
263
|
+
@pagination[:total_pages])
|
264
|
+
end
|
280
265
|
|
281
|
-
|
266
|
+
@states = @checks.each_with_object({}) do |check, memo|
|
267
|
+
memo[check[:id]] = check_state(check, time)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
erb 'checks.html'.to_sym
|
282
272
|
end
|
283
273
|
|
284
|
-
get '/
|
274
|
+
get '/checks/:id' do
|
275
|
+
check_id = params[:id]
|
285
276
|
|
286
|
-
@
|
287
|
-
@check = params[:check]
|
277
|
+
@current_time = DateTime.now
|
288
278
|
|
289
|
-
|
290
|
-
|
279
|
+
# contacts.media will also return contacts, per JSONAPI v1 relationships
|
280
|
+
@check = Flapjack::Diner.checks(check_id,
|
281
|
+
:include => ['contacts.media', 'current_state',
|
282
|
+
'latest_notifications',
|
283
|
+
'current_scheduled_maintenances',
|
284
|
+
'current_unscheduled_maintenance'])
|
291
285
|
|
292
|
-
|
286
|
+
halt(404, "Could not find check '#{check_id}'") if @check.nil?
|
293
287
|
|
294
|
-
@
|
295
|
-
@
|
296
|
-
@check_last_update = entity_check.last_update
|
297
|
-
@check_last_change = last_change
|
298
|
-
@check_summary = entity_check.summary
|
299
|
-
@check_details = entity_check.details
|
300
|
-
@check_perfdata = entity_check.perfdata
|
288
|
+
@contacts = []
|
289
|
+
@media_by_contact_id = {}
|
301
290
|
|
302
|
-
@
|
303
|
-
Flapjack::DEFAULT_INITIAL_FAILURE_DELAY
|
304
|
-
@check_repeat_failure_delay = entity_check.repeat_failure_delay ||
|
305
|
-
Flapjack::DEFAULT_REPEAT_FAILURE_DELAY
|
291
|
+
@state = check_extra_state(@check, @current_time)
|
306
292
|
|
307
|
-
@
|
308
|
-
@check_repeat_failure_delay_is_default = entity_check.repeat_failure_delay ? false : true
|
293
|
+
@contacts = Flapjack::Diner.related(@check, :contacts)
|
309
294
|
|
310
|
-
@
|
295
|
+
@media_by_contact_id = @contacts.inject({}) do |memo, contact|
|
296
|
+
memo[contact[:id]] = Flapjack::Diner.related(contact, :media)
|
297
|
+
memo
|
298
|
+
end
|
299
|
+
|
300
|
+
# these two requests will only get first page of 20 records, which is what we want
|
301
|
+
state_links = Flapjack::Diner.check_link_states(check_id,
|
302
|
+
:include => 'states')
|
311
303
|
|
312
|
-
|
313
|
-
|
304
|
+
incl = Flapjack::Diner.included_data
|
305
|
+
unless incl.nil?
|
306
|
+
@state_changes = incl['state'].nil? ? [] : incl['state'].values
|
307
|
+
end
|
314
308
|
|
315
|
-
|
316
|
-
|
309
|
+
sm_links = Flapjack::Diner.check_link_scheduled_maintenances(check_id,
|
310
|
+
:include => 'scheduled_maintenances')
|
317
311
|
|
318
|
-
|
312
|
+
incl = Flapjack::Diner.included_data
|
313
|
+
unless incl.nil?
|
314
|
+
@scheduled_maintenances = incl['scheduled_maintenance'].nil? ? [] : incl['scheduled_maintenance'].values
|
315
|
+
end
|
319
316
|
|
320
|
-
@
|
321
|
-
:order => 'desc', :limit => 20)
|
317
|
+
@error = session[:error]; session.delete(:error)
|
322
318
|
|
323
319
|
erb 'check.html'.to_sym
|
324
320
|
end
|
325
321
|
|
326
|
-
post
|
327
|
-
|
328
|
-
|
329
|
-
@summary = params[:summary]
|
330
|
-
@acknowledgement_id = params[:acknowledgement_id]
|
322
|
+
post "/acknowledgements" do
|
323
|
+
summary = params[:summary]
|
324
|
+
check_id = params[:check_id]
|
331
325
|
|
332
326
|
dur = ChronicDuration.parse(params[:duration] || '')
|
333
|
-
|
327
|
+
duration = (dur.nil? || (dur <= 0)) ? (4 * 60 * 60) : dur
|
334
328
|
|
335
|
-
|
336
|
-
|
329
|
+
# FIXME create with known id, poll a few times and return
|
330
|
+
# success/failure in session -- or maybe some AJAX method to
|
331
|
+
# show success/failure?
|
337
332
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
:
|
333
|
+
Flapjack::Diner.create_acknowledgements(:summary => summary,
|
334
|
+
:duration => duration, :check => check_id)
|
335
|
+
|
336
|
+
err = Flapjack::Diner.error
|
337
|
+
unless err.nil?
|
338
|
+
session[:error] = "Could not create the acknowledgement: #{err}"
|
339
|
+
end
|
344
340
|
|
345
341
|
redirect back
|
346
342
|
end
|
347
343
|
|
348
|
-
|
349
|
-
|
350
|
-
post '/end_unscheduled_maintenance/:entity/:check' do
|
351
|
-
@entity = params[:entity]
|
352
|
-
@check = params[:check]
|
344
|
+
patch '/unscheduled_maintenances/:id' do
|
345
|
+
unscheduled_maintenance_id = params[:id]
|
353
346
|
|
354
|
-
|
355
|
-
|
347
|
+
Flapjack::Diner.update_unscheduled_maintenances(
|
348
|
+
:id => unscheduled_maintenance_id, :end_time => Time.now)
|
356
349
|
|
357
|
-
|
350
|
+
err = Flapjack::Diner.error
|
351
|
+
unless err.nil?
|
352
|
+
session[:error] = "Could not end unscheduled maintenance: #{err}"
|
353
|
+
end
|
358
354
|
|
359
355
|
redirect back
|
360
356
|
end
|
361
357
|
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
358
|
+
post '/scheduled_maintenances' do
|
359
|
+
check_id = params[:check_id]
|
360
|
+
|
361
|
+
start_time = Chronic.parse(params[:start_time])
|
362
|
+
raise ArgumentError, "start time parsed to nil" if start_time.nil?
|
366
363
|
duration = ChronicDuration.parse(params[:duration])
|
367
364
|
summary = params[:summary]
|
368
365
|
|
369
|
-
|
370
|
-
|
366
|
+
Flapjack::Diner.create_scheduled_maintenances(:summary => summary,
|
367
|
+
:start_time => start_time, :end_time => (start_time + duration),
|
368
|
+
:check => check_id)
|
369
|
+
|
370
|
+
err = Flapjack::Diner.error
|
371
|
+
unless err.nil?
|
372
|
+
Flapjack.logger.info "Could not create scheduled maintenance: #{err}"
|
373
|
+
session[:error] = "Could not create scheduled maintenance for the check."
|
374
|
+
end
|
371
375
|
|
372
|
-
entity_check.create_scheduled_maintenance(start_time, duration,
|
373
|
-
:summary => summary)
|
374
376
|
redirect back
|
375
377
|
end
|
376
378
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
379
|
+
patch '/checks/:id' do
|
380
|
+
check_id = params[:id]
|
381
|
+
|
382
|
+
Flapjack::Diner.update_checks(:id => check_id, :enabled => false)
|
383
|
+
|
384
|
+
err = Flapjack::Diner.error
|
385
|
+
unless err.nil?
|
386
|
+
Flapjack.logger.info "Could not disable check: #{err}"
|
387
|
+
session[:error] = "Could not disable the check."
|
388
|
+
end
|
389
|
+
|
390
|
+
redirect '/'
|
391
|
+
end
|
392
|
+
|
393
|
+
patch '/scheduled_maintenances/:id' do
|
394
|
+
scheduled_maintenance_id = params[:id]
|
395
|
+
|
396
|
+
Flapjack::Diner.update_scheduled_maintenances({:id => scheduled_maintenance_id,
|
397
|
+
:end_time => Time.now})
|
398
|
+
|
399
|
+
err = Flapjack::Diner.error
|
400
|
+
unless err.nil?
|
401
|
+
Flapjack.logger.info "Could not end scheduled maintenance: #{err}"
|
402
|
+
session[:error] = "Could not end scheduled maintenance."
|
403
|
+
end
|
381
404
|
|
382
|
-
entity_check.end_scheduled_maintenance(params[:start_time].to_i)
|
383
405
|
redirect back
|
384
406
|
end
|
385
407
|
|
386
|
-
#
|
387
|
-
|
388
|
-
|
389
|
-
|
408
|
+
# FIXME should fail if its start time or end_time is in the past
|
409
|
+
# we'll allow the API to delete without fear or favour though
|
410
|
+
delete '/scheduled_maintenances/:id' do
|
411
|
+
scheduled_maintenance_id = params[:id]
|
412
|
+
|
413
|
+
Flapjack::Diner.delete_scheduled_maintenances(scheduled_maintenance_id)
|
414
|
+
|
415
|
+
err = Flapjack::Diner.error
|
416
|
+
unless err.nil?
|
417
|
+
Flapjack.logger.info "Could not delete scheduled maintenance: #{err}"
|
418
|
+
session[:error] = "Could not delete scheduled maintenance."
|
419
|
+
end
|
390
420
|
|
391
|
-
entity_check.disable!
|
392
421
|
redirect back
|
393
422
|
end
|
394
423
|
|
395
424
|
get '/contacts' do
|
396
|
-
|
425
|
+
opts = {}
|
426
|
+
@name = params[:name]
|
427
|
+
opts.update(:name => @name) unless @name.nil?
|
428
|
+
|
429
|
+
@contacts = Flapjack::Diner.contacts(:page => params[:page] || 1,
|
430
|
+
:filter => opts, :sort => '+name')
|
431
|
+
|
432
|
+
unless @contacts.nil?
|
433
|
+
@pagination = pagination_from_context(Flapjack::Diner.context)
|
434
|
+
unless @pagination.nil?
|
435
|
+
@links = create_pagination_links(@pagination[:page],
|
436
|
+
@pagination[:total_pages])
|
437
|
+
end
|
438
|
+
end
|
397
439
|
|
398
440
|
erb 'contacts.html'.to_sym
|
399
441
|
end
|
400
442
|
|
401
|
-
get
|
402
|
-
|
403
|
-
end
|
404
|
-
|
405
|
-
get "/contacts/:contact" do
|
406
|
-
contact_id = params[:contact]
|
407
|
-
halt(404, "No contact id") if contact_id.nil?
|
443
|
+
get "/contacts/:id" do
|
444
|
+
contact_id = params[:id]
|
408
445
|
|
409
|
-
@contact = Flapjack::
|
446
|
+
@contact = Flapjack::Diner.contacts(contact_id,
|
447
|
+
:include => ['checks', 'media.alerting_checks',
|
448
|
+
'rules.tags', 'rules.media'])
|
410
449
|
halt(404, "Could not find contact '#{contact_id}'") if @contact.nil?
|
411
450
|
|
412
|
-
|
413
|
-
|
451
|
+
@checks = []
|
452
|
+
@media = []
|
453
|
+
@rules = []
|
454
|
+
|
455
|
+
@alerting_checks_by_media_id = {}
|
456
|
+
|
457
|
+
@tags_by_rule_id = {}
|
458
|
+
@media_by_rule_id = {}
|
459
|
+
|
460
|
+
@checks = Flapjack::Diner.related(@contact, :checks)
|
461
|
+
@media = Flapjack::Diner.related(@contact, :media)
|
462
|
+
|
463
|
+
unless @media.nil? || @media.empty?
|
464
|
+
@alerting_checks_by_media_id = @media.inject({}) do |memo, medium|
|
465
|
+
memo[medium[:id]] = Flapjack::Diner.related(medium, :alerting_checks)
|
466
|
+
memo
|
467
|
+
end
|
414
468
|
end
|
415
469
|
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
470
|
+
@rules = Flapjack::Diner.related(@contact, :rules)
|
471
|
+
|
472
|
+
unless @rules.nil? || @rules.empty?
|
473
|
+
@tags_by_rule_id = @rules.inject({}) do |memo, rule|
|
474
|
+
memo[rule[:id]] = Flapjack::Diner.related(rule, :tags)
|
475
|
+
memo
|
476
|
+
end
|
477
|
+
|
478
|
+
@media_by_rule_id = @rules.inject({}) do |memo, rule|
|
479
|
+
memo[rule[:id]] = Flapjack::Diner.related(rule, :media)
|
480
|
+
memo
|
481
|
+
end
|
482
|
+
end
|
420
483
|
|
421
484
|
erb 'contact.html'.to_sym
|
422
485
|
end
|
423
486
|
|
424
|
-
|
487
|
+
error do
|
488
|
+
e = env['sinatra.error']
|
489
|
+
# trace = e.backtrace.join("\n")
|
490
|
+
# puts trace
|
425
491
|
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
492
|
+
# Rack::CommonLogger doesn't log requests which result in exceptions.
|
493
|
+
# If you want something done properly, do it yourself...
|
494
|
+
access_log = self.class.instance_variable_get('@middleware').detect {|mw|
|
495
|
+
mw.first.is_a?(::Rack::CommonLogger)
|
496
|
+
}
|
497
|
+
unless access_log.nil?
|
498
|
+
access_log.first.send(:log, status_code,
|
499
|
+
::Rack::Utils::HeaderHash.new(headers), msg,
|
500
|
+
env['request_timestamp'])
|
501
|
+
end
|
502
|
+
self.class.instance_variable_get('@show_exceptions').pretty(env, e)
|
431
503
|
end
|
432
504
|
|
433
|
-
|
434
|
-
entity = Flapjack::Data::Entity.find_by_name(entity_name,
|
435
|
-
:redis => redis)
|
436
|
-
return ['-', '-', 'never', 'never', false, false, 'never'] if entity.nil?
|
437
|
-
entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
|
438
|
-
check, :redis => redis)
|
439
|
-
summary = entity_check.summary
|
440
|
-
summary = summary[0..76] + '...' unless (summary.nil? || (summary.length < 81))
|
441
|
-
latest_notif =
|
442
|
-
{:problem => entity_check.last_notification_for_state(:problem)[:timestamp],
|
443
|
-
:recovery => entity_check.last_notification_for_state(:recovery)[:timestamp],
|
444
|
-
:acknowledgement => entity_check.last_notification_for_state(:acknowledgement)[:timestamp]
|
445
|
-
}.max_by {|n| n[1] || 0}
|
446
|
-
|
447
|
-
lc = entity_check.last_change
|
448
|
-
last_change = lc ? (ChronicDuration.output(Time.now.to_i - lc.to_i,
|
449
|
-
:format => :short, :keep_zero => true, :units => 2) || '0s') : 'never'
|
450
|
-
|
451
|
-
lu = entity_check.last_update
|
452
|
-
last_update = lu ? (ChronicDuration.output(Time.now.to_i - lu.to_i,
|
453
|
-
:format => :short, :keep_zero => true, :units => 2) || '0s') : 'never'
|
454
|
-
|
455
|
-
ln = latest_notif[1]
|
456
|
-
last_notified = ln ? (ChronicDuration.output(Time.now.to_i - ln.to_i,
|
457
|
-
:format => :short, :keep_zero => true, :units => 2) || '0s') + ", #{latest_notif[0]}" : 'never'
|
458
|
-
|
459
|
-
[(entity_check.state || '-'),
|
460
|
-
(summary || '-'),
|
461
|
-
last_change,
|
462
|
-
last_update,
|
463
|
-
entity_check.in_unscheduled_maintenance?,
|
464
|
-
entity_check.in_scheduled_maintenance?,
|
465
|
-
last_notified
|
466
|
-
]
|
467
|
-
end
|
505
|
+
private
|
468
506
|
|
469
|
-
def
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
event_counters = redis.hgetall("event_counters:#{instance_id}")
|
480
|
-
event_rates = event_counters.inject({}) do |er, ec|
|
481
|
-
er[ec[0]] = uptime && uptime > 0 ? (ec[1].to_f / uptime).round : nil
|
482
|
-
er
|
507
|
+
def check_state(check, time)
|
508
|
+
current_state = Flapjack::Diner.related(check, :current_state)
|
509
|
+
|
510
|
+
last_changed = if current_state.nil? || current_state[:created_at].nil?
|
511
|
+
nil
|
512
|
+
else
|
513
|
+
begin
|
514
|
+
DateTime.parse(current_state[:created_at])
|
515
|
+
rescue ArgumentError
|
516
|
+
Flapjack.logger.warn("error parsing check state :created_at ( #{current_state.inspect} )")
|
483
517
|
end
|
484
|
-
memo[instance_id] = {
|
485
|
-
'boot_time' => boot_time,
|
486
|
-
'uptime' => uptime,
|
487
|
-
'uptime_string' => uptime_string,
|
488
|
-
'event_counters' => event_counters,
|
489
|
-
'event_rates' => event_rates
|
490
|
-
}
|
491
|
-
memo
|
492
518
|
end
|
493
|
-
@event_counters = redis.hgetall('event_counters')
|
494
|
-
@events_queued = redis.llen('events')
|
495
|
-
@current_checks_ages = Flapjack::Data::EntityCheck.find_all_split_by_freshness([0, 60, 300, 900, 3600], {:redis => redis, :logger => logger, :counts => true } )
|
496
|
-
end
|
497
519
|
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
520
|
+
last_updated = if current_state.nil? || current_state[:updated_at].nil?
|
521
|
+
nil
|
522
|
+
else
|
523
|
+
begin
|
524
|
+
DateTime.parse(current_state[:updated_at])
|
525
|
+
rescue ArgumentError
|
526
|
+
Flapjack.logger.warn("error parsing check state :updated_at ( #{current_state.inspect} )")
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
latest_notifications = Flapjack::Diner.related(check, :latest_notifications)
|
502
531
|
|
503
|
-
|
504
|
-
|
505
|
-
|
532
|
+
current_scheduled_maintenances = Flapjack::Diner.related(check, :current_scheduled_maintenances)
|
533
|
+
current_scheduled_maintenance = current_scheduled_maintenances.max_by do |sm|
|
534
|
+
begin
|
535
|
+
DateTime.parse(sm[:end_time]).to_i
|
536
|
+
rescue ArgumentError
|
537
|
+
Flapjack.logger.warn "Couldn't parse time from current_scheduled_maintenances"
|
538
|
+
-1
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
in_scheduled_maintenance = !current_scheduled_maintenance.nil?
|
543
|
+
|
544
|
+
current_unscheduled_maintenance = Flapjack::Diner.related(check, :current_unscheduled_maintenance)
|
545
|
+
in_unscheduled_maintenance = !current_unscheduled_maintenance.nil?
|
546
|
+
|
547
|
+
{
|
548
|
+
:condition => current_state.nil? ? '-' : current_state[:condition],
|
549
|
+
:summary => current_state.nil? ? '-' : current_state[:summary],
|
550
|
+
:latest_notifications => (latest_notifications || []),
|
551
|
+
:last_changed => last_changed,
|
552
|
+
:last_updated => last_updated,
|
553
|
+
:in_scheduled_maintenance => in_scheduled_maintenance,
|
554
|
+
:in_unscheduled_maintenance => in_unscheduled_maintenance
|
555
|
+
}
|
506
556
|
end
|
507
557
|
|
508
|
-
def
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
558
|
+
def check_extra_state(check, time)
|
559
|
+
state = check_state(check, time)
|
560
|
+
|
561
|
+
current_state = Flapjack::Diner.related(check, :current_state)
|
562
|
+
|
563
|
+
current_scheduled_maintenances = Flapjack::Diner.related(check, :current_scheduled_maintenances)
|
564
|
+
current_scheduled_maintenance = current_scheduled_maintenances.max_by do |sm|
|
565
|
+
begin
|
566
|
+
DateTime.parse(sm[:end_time]).to_i
|
567
|
+
rescue ArgumentError
|
568
|
+
Flapjack.logger.warn "Couldn't parse time from current_scheduled_maintenances"
|
569
|
+
-1
|
516
570
|
end
|
517
|
-
memo
|
518
571
|
end
|
572
|
+
|
573
|
+
current_unscheduled_maintenance = Flapjack::Diner.related(check, :current_unscheduled_maintenance)
|
574
|
+
|
575
|
+
state.merge(
|
576
|
+
:details => current_state.nil? ? '-' : current_state[:details],
|
577
|
+
:perfdata => current_state.nil? ? '-' : current_state[:perfdata],
|
578
|
+
:current_scheduled_maintenances => (current_scheduled_maintenances || []),
|
579
|
+
:current_scheduled_maintenance => current_scheduled_maintenance,
|
580
|
+
:current_unscheduled_maintenance => current_unscheduled_maintenance,
|
581
|
+
)
|
519
582
|
end
|
520
583
|
|
521
|
-
def
|
522
|
-
|
523
|
-
@required_css += css
|
584
|
+
def pagination_from_context(context)
|
585
|
+
((context || {})[:meta] || {})[:pagination]
|
524
586
|
end
|
525
587
|
|
526
588
|
def require_js(*js)
|
@@ -529,24 +591,24 @@ module Flapjack
|
|
529
591
|
@required_js.uniq!
|
530
592
|
end
|
531
593
|
|
594
|
+
def require_css(*css)
|
595
|
+
@required_css ||= []
|
596
|
+
@required_css += css
|
597
|
+
@required_css.uniq!
|
598
|
+
end
|
599
|
+
|
532
600
|
def include_required_js
|
533
|
-
if @required_js
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
else
|
538
|
-
""
|
539
|
-
end
|
601
|
+
return "" if @required_js.nil?
|
602
|
+
@required_js.map { |filename|
|
603
|
+
"<script type='text/javascript' src='#{link_to("js/#{filename}.js")}'></script>"
|
604
|
+
}.join("\n ")
|
540
605
|
end
|
541
606
|
|
542
607
|
def include_required_css
|
543
|
-
if @required_css
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
else
|
548
|
-
""
|
549
|
-
end
|
608
|
+
return "" if @required_css.nil?
|
609
|
+
@required_css.map { |filename|
|
610
|
+
%(<link rel="stylesheet" href="#{link_to("css/#{filename}.css")}" media="screen">)
|
611
|
+
}.join("\n ")
|
550
612
|
end
|
551
613
|
|
552
614
|
# from http://gist.github.com/98310
|
@@ -573,7 +635,37 @@ module Flapjack
|
|
573
635
|
end
|
574
636
|
|
575
637
|
def include_page_title
|
576
|
-
|
638
|
+
if instance_variable_defined?('@page_title') && !@page_title.nil?
|
639
|
+
return "#{@page_title} | Flapjack"
|
640
|
+
end
|
641
|
+
"Flapjack"
|
642
|
+
end
|
643
|
+
|
644
|
+
def boolean_from_str(str)
|
645
|
+
case str
|
646
|
+
when '0', 'f', 'false', 'n', 'no'
|
647
|
+
false
|
648
|
+
when '1', 't', 'true', 'y', 'yes'
|
649
|
+
true
|
650
|
+
end
|
651
|
+
end
|
652
|
+
|
653
|
+
def create_pagination_links(page, total_pages)
|
654
|
+
pages = {}
|
655
|
+
pages[:first] = 1
|
656
|
+
pages[:prev] = page - 1 if (page > 1)
|
657
|
+
pages[:next] = page + 1 if page < total_pages
|
658
|
+
pages[:last] = total_pages
|
659
|
+
|
660
|
+
url_without_params = request.url.split('?').first
|
661
|
+
|
662
|
+
links = {}
|
663
|
+
pages.each do |key, value|
|
664
|
+
page_params = {'page' => value }
|
665
|
+
new_params = request.params.merge(page_params)
|
666
|
+
links[key] = "#{url_without_params}?#{new_params.to_query}"
|
667
|
+
end
|
668
|
+
links
|
577
669
|
end
|
578
670
|
end
|
579
671
|
end
|