flapjack 1.6.0 → 2.0.0b1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
data/lib/flapjack/data/alert.rb
CHANGED
|
@@ -1,147 +1,110 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
|
-
require 'digest'
|
|
4
|
-
|
|
5
3
|
require 'active_support/inflector'
|
|
4
|
+
|
|
5
|
+
require 'zermelo/records/redis'
|
|
6
|
+
|
|
6
7
|
require 'flapjack/utility'
|
|
7
8
|
|
|
9
|
+
require 'flapjack/data/condition'
|
|
10
|
+
require 'flapjack/data/state'
|
|
11
|
+
|
|
8
12
|
# Alert is the object ready to send to someone, complete with an address and all
|
|
9
13
|
# the data with which to render the text of the alert in the appropriate gateway
|
|
10
|
-
#
|
|
11
|
-
# It should possibly be renamed AlertPresenter
|
|
12
14
|
|
|
13
15
|
module Flapjack
|
|
14
16
|
module Data
|
|
15
17
|
class Alert
|
|
16
18
|
|
|
17
|
-
# from Flapjack::Data::Notification
|
|
18
|
-
attr_reader :event_id,
|
|
19
|
-
:state,
|
|
20
|
-
:summary,
|
|
21
|
-
:acknowledgement_duration,
|
|
22
|
-
:last_state,
|
|
23
|
-
:last_summary,
|
|
24
|
-
:state_duration,
|
|
25
|
-
:details,
|
|
26
|
-
:time,
|
|
27
|
-
:notification_type,
|
|
28
|
-
:event_count,
|
|
29
|
-
:tags
|
|
30
|
-
|
|
31
|
-
# from Flapjack::Data::Message
|
|
32
|
-
# :id,
|
|
33
|
-
attr_reader :media,
|
|
34
|
-
:address,
|
|
35
|
-
:rollup,
|
|
36
|
-
:contact_id,
|
|
37
|
-
:contact_first_name,
|
|
38
|
-
:contact_last_name
|
|
39
|
-
|
|
40
|
-
# from Flapjack::Notifier
|
|
41
|
-
attr_reader :rollup_threshold,
|
|
42
|
-
:rollup_alerts,
|
|
43
|
-
:in_scheduled_maintenance,
|
|
44
|
-
:in_unscheduled_maintenance
|
|
45
|
-
|
|
46
|
-
# from self
|
|
47
|
-
attr_reader :entity,
|
|
48
|
-
:check,
|
|
49
|
-
:notification_id,
|
|
50
|
-
:event_hash
|
|
51
|
-
|
|
52
19
|
include Flapjack::Utility
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
raise "state_duration (#{@state_duration.inspect}) is invalid" unless
|
|
94
|
-
@state_duration.is_a?(Integer) && @state_duration >= 0
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
if @rollup_alerts
|
|
98
|
-
raise "rollup_alerts should be nil or a hash" unless @rollup_alerts.is_a?(Hash)
|
|
99
|
-
@rollup_alerts.each_pair do |check, details|
|
|
100
|
-
raise "duration of rollup_alerts['#{check}'] must be an integer" unless
|
|
101
|
-
details['duration'] && details['duration'].is_a?(Integer)
|
|
102
|
-
raise "state of rollup_alerts['#{check}'] is invalid" unless
|
|
103
|
-
details['state'] && allowed_rollup_states.include?(details['state'])
|
|
20
|
+
include Zermelo::Records::RedisSet
|
|
21
|
+
|
|
22
|
+
define_attributes :condition => :string,
|
|
23
|
+
:action => :string,
|
|
24
|
+
:summary => :string,
|
|
25
|
+
:details => :string,
|
|
26
|
+
:last_condition => :string,
|
|
27
|
+
:last_action => :string,
|
|
28
|
+
:last_summary => :string,
|
|
29
|
+
:event_count => :integer,
|
|
30
|
+
:time => :timestamp,
|
|
31
|
+
:acknowledgement_duration => :integer, # passed in as duration in other code
|
|
32
|
+
:condition_duration => :float,
|
|
33
|
+
:rollup => :string,
|
|
34
|
+
:rollup_states_json => :string,
|
|
35
|
+
:event_hash => :string
|
|
36
|
+
|
|
37
|
+
belongs_to :medium, :class_name => 'Flapjack::Data::Medium', :inverse_of => :alerts
|
|
38
|
+
|
|
39
|
+
belongs_to :check, :class_name => 'Flapjack::Data::Check', :inverse_of => :alerts
|
|
40
|
+
|
|
41
|
+
validates :condition, :unless => proc {|s| !s.action.nil? },
|
|
42
|
+
:inclusion => { :in => Flapjack::Data::Condition.healthy.keys +
|
|
43
|
+
Flapjack::Data::Condition.unhealthy.keys }
|
|
44
|
+
|
|
45
|
+
validates :action, :allow_nil => true, :inclusion => {:in => Flapjack::Data::State::ACTIONS}
|
|
46
|
+
|
|
47
|
+
validates :condition_duration, :presence => true, :allow_nil => true,
|
|
48
|
+
:numericality => {:minimum => 0}, :unless => proc {|n| n.type == 'test'}
|
|
49
|
+
|
|
50
|
+
validates_each :rollup_states_json do |record, att, value|
|
|
51
|
+
unless value.nil?
|
|
52
|
+
states = Flapjack.load_json(value)
|
|
53
|
+
case states
|
|
54
|
+
when Hash
|
|
55
|
+
record.errors.add(att, 'must contain a serialized Hash (String => Array[String])') unless states.all? {|k,v|
|
|
56
|
+
k.is_a?(String) && v.is_a?(Array) && v.all?{|vs| vs.is_a?(String)}
|
|
57
|
+
}
|
|
58
|
+
else
|
|
59
|
+
record.errors.add(att, 'must contain a serialized Hash (String => Array[String])')
|
|
104
60
|
end
|
|
105
61
|
end
|
|
106
62
|
end
|
|
107
63
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
64
|
+
# TODO handle JSON exception
|
|
65
|
+
def rollup_states
|
|
66
|
+
if self.rollup_states_json.nil?
|
|
67
|
+
@rollup_states = nil
|
|
68
|
+
return
|
|
69
|
+
end
|
|
70
|
+
@rollup_states = Flapjack.load_json(self.rollup_states_json)
|
|
111
71
|
end
|
|
112
72
|
|
|
113
|
-
def
|
|
114
|
-
|
|
73
|
+
def rollup_states=(rollup_states)
|
|
74
|
+
@rollup_states = rollup_states
|
|
75
|
+
self.rollup_states_json = rollup_states.nil? ? nil : Flapjack.dump_json(rollup_states)
|
|
76
|
+
end
|
|
115
77
|
|
|
116
|
-
|
|
117
|
-
|
|
78
|
+
def notification_type
|
|
79
|
+
self.class.notification_type(action, condition)
|
|
80
|
+
end
|
|
118
81
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
82
|
+
def self.notification_type(act, cond)
|
|
83
|
+
case act
|
|
84
|
+
when 'acknowledgement'
|
|
85
|
+
'acknowledgement'
|
|
86
|
+
when /\Atest_notifications(?:\s+#{Flapjack::Data::Condition.unhealthy.keys.join('|')})?\z/
|
|
87
|
+
'test'
|
|
88
|
+
when nil
|
|
89
|
+
case cond
|
|
90
|
+
when 'ok'
|
|
91
|
+
'recovery'
|
|
92
|
+
when 'warning', 'critical', 'unknown'
|
|
93
|
+
'problem'
|
|
94
|
+
else
|
|
95
|
+
'unknown'
|
|
130
96
|
end
|
|
131
|
-
return nil
|
|
132
97
|
end
|
|
133
|
-
return if 'shutdown'.eql?(parsed['notification_type'])
|
|
134
|
-
self.new( parsed, :logger => opts[:logger] )
|
|
135
98
|
end
|
|
136
99
|
|
|
137
100
|
def type
|
|
138
|
-
case
|
|
101
|
+
case self.rollup
|
|
139
102
|
when "problem"
|
|
140
103
|
"rollup_problem"
|
|
141
104
|
when "recovery"
|
|
142
105
|
"rollup_recovery"
|
|
143
106
|
else
|
|
144
|
-
|
|
107
|
+
notification_type
|
|
145
108
|
end
|
|
146
109
|
end
|
|
147
110
|
|
|
@@ -156,61 +119,51 @@ module Flapjack
|
|
|
156
119
|
end
|
|
157
120
|
end
|
|
158
121
|
|
|
159
|
-
def
|
|
160
|
-
|
|
122
|
+
def state
|
|
123
|
+
@state ||= (self.action || self.condition)
|
|
161
124
|
end
|
|
162
125
|
|
|
163
|
-
def
|
|
164
|
-
|
|
126
|
+
def last_state
|
|
127
|
+
@last_state ||= (self.last_action || self.last_condition)
|
|
165
128
|
end
|
|
166
129
|
|
|
167
|
-
def
|
|
168
|
-
['
|
|
169
|
-
alerts = rollup_alerts.find_all {|alert| alert[1]['state'] == state}
|
|
170
|
-
memo[state] = alerts
|
|
171
|
-
memo
|
|
172
|
-
end
|
|
130
|
+
def state_title_case
|
|
131
|
+
['ok'].include?(state) ? state.upcase : state.titleize
|
|
173
132
|
end
|
|
174
133
|
|
|
175
|
-
def
|
|
176
|
-
|
|
177
|
-
memo[alert[1]['state']] = (memo[alert[1]['state']] || 0) + 1
|
|
178
|
-
memo
|
|
179
|
-
end
|
|
134
|
+
def last_state_title_case
|
|
135
|
+
['ok'].include?(last_state) ? last_state.upcase : last_state.titleize
|
|
180
136
|
end
|
|
181
137
|
|
|
182
138
|
def rollup_states_summary
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
memo << "#{state.titleize}: #{state_counts[state]}"
|
|
187
|
-
memo
|
|
139
|
+
return '' if rollup_states.nil?
|
|
140
|
+
rollup_states.each_with_object([]) do |(alert_state, alerts), memo|
|
|
141
|
+
memo << "#{alert_state.titleize}: #{alerts.size}"
|
|
188
142
|
end.join(', ')
|
|
189
143
|
end
|
|
190
144
|
|
|
191
145
|
# produces a textual list of checks that are failing broken down by state, eg:
|
|
192
146
|
# Critical: 'PING' on 'foo-app-01.example.com', 'SSH' on 'foo-app-01.example.com';
|
|
193
147
|
# Warning: 'Disk / Utilisation' on 'foo-app-02.example.com'
|
|
194
|
-
def rollup_states_detail_text(opts)
|
|
148
|
+
def rollup_states_detail_text(opts = {})
|
|
149
|
+
return '' if rollup_states.nil?
|
|
195
150
|
max_checks = opts[:max_checks_per_state]
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
checks << '...' if checks.length < rollup_state_counts[state[0]]
|
|
202
|
-
memo << "#{state[0].titleize}: #{checks.join(', ')}"
|
|
203
|
-
memo
|
|
151
|
+
rollup_states.each_with_object([]) do |(alert_state, alerts), memo|
|
|
152
|
+
alerts = alerts[0..(max_checks - 1)] unless max_checks.nil? || (max_checks <= 0)
|
|
153
|
+
next if alerts.empty?
|
|
154
|
+
alerts << '...' if alerts.size < rollup_states[alert_state].size
|
|
155
|
+
memo << "#{alert_state.titleize}: #{alerts.join(', ')}"
|
|
204
156
|
end.join('; ')
|
|
205
157
|
end
|
|
206
158
|
|
|
207
159
|
def to_s
|
|
208
|
-
|
|
160
|
+
contact = medium.contact
|
|
161
|
+
msg = "Alert via #{medium.transport}:#{medium.address} to contact #{contact.id} (#{contact.name}): "
|
|
209
162
|
msg += type_sentence_case
|
|
210
163
|
if rollup
|
|
211
164
|
msg += " - #{rollup_states_summary} (#{rollup_states_detail_text(:max_checks_per_state => 3)})"
|
|
212
165
|
else
|
|
213
|
-
msg += " - '#{check}'
|
|
166
|
+
msg += " - '#{self.check.name}'"
|
|
214
167
|
unless ['acknowledgement', 'test'].include?(type)
|
|
215
168
|
msg += " is #{state_title_case}"
|
|
216
169
|
end
|
|
@@ -223,20 +176,6 @@ module Flapjack
|
|
|
223
176
|
end
|
|
224
177
|
end
|
|
225
178
|
end
|
|
226
|
-
|
|
227
|
-
def record_send_success!
|
|
228
|
-
@logger.info "Sent alert successfully: #{to_s}"
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
# TODO: perhaps move message send failure porting to this method
|
|
232
|
-
# to avoid duplication in the gateways, and to more easily allow
|
|
233
|
-
# better error reporting on message generation / send failure
|
|
234
|
-
#def record_send_failure!(opts)
|
|
235
|
-
# exception = opts[:exception]
|
|
236
|
-
# message = opts[:message]
|
|
237
|
-
# @logger.error "Error sending an alert! #{alert}"
|
|
238
|
-
#end
|
|
239
|
-
|
|
240
179
|
end
|
|
241
180
|
end
|
|
242
181
|
end
|
|
@@ -0,0 +1,611 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'digest'
|
|
4
|
+
|
|
5
|
+
require 'swagger/blocks'
|
|
6
|
+
|
|
7
|
+
require 'zermelo/records/redis'
|
|
8
|
+
|
|
9
|
+
require 'flapjack/data/extensions/short_name'
|
|
10
|
+
require 'flapjack/data/validators/id_validator'
|
|
11
|
+
|
|
12
|
+
require 'flapjack/data/condition'
|
|
13
|
+
require 'flapjack/data/state'
|
|
14
|
+
require 'flapjack/data/unscheduled_maintenance'
|
|
15
|
+
|
|
16
|
+
require 'flapjack/data/extensions/associations'
|
|
17
|
+
require 'flapjack/data/extensions/short_name'
|
|
18
|
+
|
|
19
|
+
require 'flapjack/gateways/jsonapi/data/join_descriptor'
|
|
20
|
+
require 'flapjack/gateways/jsonapi/data/method_descriptor'
|
|
21
|
+
|
|
22
|
+
module Flapjack
|
|
23
|
+
module Data
|
|
24
|
+
class Check
|
|
25
|
+
|
|
26
|
+
include Zermelo::Records::RedisSet
|
|
27
|
+
include ActiveModel::Serializers::JSON
|
|
28
|
+
self.include_root_in_json = false
|
|
29
|
+
include Swagger::Blocks
|
|
30
|
+
|
|
31
|
+
include Flapjack::Data::Extensions::Associations
|
|
32
|
+
include Flapjack::Data::Extensions::ShortName
|
|
33
|
+
|
|
34
|
+
define_attributes :name => :string,
|
|
35
|
+
:enabled => :boolean,
|
|
36
|
+
:ack_hash => :string,
|
|
37
|
+
:initial_failure_delay => :integer,
|
|
38
|
+
:repeat_failure_delay => :integer,
|
|
39
|
+
:notification_count => :integer,
|
|
40
|
+
:condition => :string,
|
|
41
|
+
:failing => :boolean,
|
|
42
|
+
:alertable => :boolean
|
|
43
|
+
|
|
44
|
+
index_by :enabled, :failing, :alertable
|
|
45
|
+
unique_index_by :name, :ack_hash
|
|
46
|
+
|
|
47
|
+
# TODO validate uniqueness of :name, :ack_hash
|
|
48
|
+
|
|
49
|
+
has_and_belongs_to_many :tags, :class_name => 'Flapjack::Data::Tag',
|
|
50
|
+
:inverse_of => :checks
|
|
51
|
+
|
|
52
|
+
has_sorted_set :scheduled_maintenances,
|
|
53
|
+
:class_name => 'Flapjack::Data::ScheduledMaintenance',
|
|
54
|
+
:key => :start_time, :order => :desc, :inverse_of => :check
|
|
55
|
+
|
|
56
|
+
has_sorted_set :unscheduled_maintenances,
|
|
57
|
+
:class_name => 'Flapjack::Data::UnscheduledMaintenance',
|
|
58
|
+
:key => :start_time, :order => :desc, :inverse_of => :check
|
|
59
|
+
|
|
60
|
+
has_sorted_set :states, :class_name => 'Flapjack::Data::State',
|
|
61
|
+
:key => :created_at, :order => :desc, :inverse_of => :check
|
|
62
|
+
|
|
63
|
+
# shortcut to expose the latest of the above to the API
|
|
64
|
+
has_one :current_state, :class_name => 'Flapjack::Data::State',
|
|
65
|
+
:inverse_of => :current_check
|
|
66
|
+
|
|
67
|
+
has_sorted_set :latest_notifications, :class_name => 'Flapjack::Data::State',
|
|
68
|
+
:key => :created_at, :order => :desc, :inverse_of => :latest_notifications_check,
|
|
69
|
+
:after_remove => :destroy_states
|
|
70
|
+
|
|
71
|
+
def self.destroy_states(check_id, *st_ids)
|
|
72
|
+
# states won't be deleted if still referenced elsewhere -- see the State
|
|
73
|
+
# before_destroy callback
|
|
74
|
+
Flapjack::Data::State.intersect(:id => st_ids).destroy_all
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# the following associations are used internally, for the notification
|
|
78
|
+
# and alert queue inter-pikelet workflow
|
|
79
|
+
has_one :most_severe, :class_name => 'Flapjack::Data::State',
|
|
80
|
+
:inverse_of => :most_severe_check, :after_clear => :destroy_states
|
|
81
|
+
|
|
82
|
+
has_many :notifications, :class_name => 'Flapjack::Data::Notification',
|
|
83
|
+
:inverse_of => :check
|
|
84
|
+
|
|
85
|
+
has_many :alerts, :class_name => 'Flapjack::Data::Alert',
|
|
86
|
+
:inverse_of => :check
|
|
87
|
+
|
|
88
|
+
# this can be called from the API (with no args) or from notifier.rb
|
|
89
|
+
# (which will pass a severity to use, and an effective time)
|
|
90
|
+
def alerting_media(opts = {})
|
|
91
|
+
time = opts[:time] || Time.now
|
|
92
|
+
severity = opts[:severity] || self.condition
|
|
93
|
+
|
|
94
|
+
# return empty set if disabled, or in a maintenance period (for API only,
|
|
95
|
+
# these will have been checked already in processor if called by notifier)
|
|
96
|
+
if opts.empty?
|
|
97
|
+
unless self.enabled
|
|
98
|
+
return Flapjack::Data::Medium.empty
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
unless self.current_unscheduled_maintenance.nil?
|
|
102
|
+
return Flapjack::Data::Medium.empty
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
start_range = Zermelo::Filters::IndexRange.new(nil, time, :by_score => true)
|
|
106
|
+
end_range = Zermelo::Filters::IndexRange.new(time, nil, :by_score => true)
|
|
107
|
+
|
|
108
|
+
unless self.scheduled_maintenances.
|
|
109
|
+
intersect(:start_time => start_range, :end_time => end_range).empty?
|
|
110
|
+
|
|
111
|
+
return Flapjack::Data::Medium.empty
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# determine matching acceptors
|
|
116
|
+
tag_ids = self.tags.ids
|
|
117
|
+
|
|
118
|
+
acceptor_ids = matching_rule_ids(tag_ids, :blackhole => false, :severity => severity)
|
|
119
|
+
acceptor_media_ids = Flapjack::Data::Rule.matching_media_ids(acceptor_ids,
|
|
120
|
+
:time => time)
|
|
121
|
+
|
|
122
|
+
return Flapjack::Data::Medium.empty if acceptor_media_ids.empty?
|
|
123
|
+
|
|
124
|
+
# and matching rejectors
|
|
125
|
+
rejector_ids = matching_rule_ids(tag_ids, :blackhole => true, :severity => severity)
|
|
126
|
+
rejector_media_ids = Flapjack::Data::Rule.matching_media_ids(rejector_ids,
|
|
127
|
+
:time => time)
|
|
128
|
+
|
|
129
|
+
unless rejector_media_ids.empty?
|
|
130
|
+
acceptor_media_ids -= rejector_media_ids
|
|
131
|
+
return Flapjack::Data::Medium.empty if acceptor_media_ids.empty?
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
Flapjack::Data::Medium.intersect(:id => acceptor_media_ids)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def contacts
|
|
138
|
+
# return empty set if disabled
|
|
139
|
+
return Flapjack::Data::Contact.empty unless self.enabled
|
|
140
|
+
|
|
141
|
+
# determine matching acceptors
|
|
142
|
+
tag_ids = self.tags.ids
|
|
143
|
+
time = Time.now
|
|
144
|
+
|
|
145
|
+
acceptor_ids = matching_rule_ids(tag_ids, :blackhole => false,)
|
|
146
|
+
acceptor_contact_ids = Flapjack::Data::Rule.matching_contact_ids(acceptor_ids,
|
|
147
|
+
:time => time)
|
|
148
|
+
return Flapjack::Data::Contact.empty if acceptor_contact_ids.empty?
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
# and matching rejectors
|
|
152
|
+
rejector_ids = matching_rule_ids(tag_ids, :blackhole => true)
|
|
153
|
+
rejector_contact_ids = Flapjack::Data::Rule.matching_contact_ids(rejector_ids,
|
|
154
|
+
:time => time)
|
|
155
|
+
unless rejector_contact_ids.empty?
|
|
156
|
+
acceptor_contact_ids -= rejector_contact_ids
|
|
157
|
+
return Flapjack::Data::Contact.empty if acceptor_contact_ids.empty?
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
Flapjack::Data::Contact.intersect(:id => acceptor_contact_ids)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def matching_rule_ids(tag_ids, opts = {})
|
|
164
|
+
severity = opts[:severity]
|
|
165
|
+
blackhole = opts[:blackhole]
|
|
166
|
+
|
|
167
|
+
matcher_by_strategy = {
|
|
168
|
+
'global' => nil,
|
|
169
|
+
'all_tags' => proc {|rule_tag_ids| (rule_tag_ids - tag_ids).empty? },
|
|
170
|
+
'any_tag' => proc {|rule_tag_ids| !((rule_tag_ids & tag_ids).empty?) },
|
|
171
|
+
'no_tag' => proc {|rule_tag_ids| (rule_tag_ids & tag_ids).empty? }
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
matcher_by_strategy.each_with_object(Set.new) do |(strategy, matcher), memo|
|
|
175
|
+
rules = Flapjack::Data::Rule.intersect(:enabled => true,
|
|
176
|
+
:blackhole => blackhole, :strategy => strategy)
|
|
177
|
+
unless severity.nil?
|
|
178
|
+
rules = rules.intersect(:conditions_list => [nil, /(?:^|,)#{severity}(?:,|$)/])
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
if matcher.nil?
|
|
182
|
+
memo.merge(rules.ids)
|
|
183
|
+
next
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
rules.associated_ids_for(:tags).each_pair do |rule_id, rule_tag_ids|
|
|
187
|
+
memo << rule_id if matcher.call(rule_tag_ids)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# end internal associations
|
|
193
|
+
|
|
194
|
+
validates :name, :presence => true
|
|
195
|
+
validates :enabled, :inclusion => {:in => [true, false]}
|
|
196
|
+
|
|
197
|
+
validates :condition, :presence => true, :unless => proc {|c| c.failing.nil? }
|
|
198
|
+
validates :failing, :inclusion => {:in => [true, false]},
|
|
199
|
+
:unless => proc {|c| c.condition.nil? }
|
|
200
|
+
|
|
201
|
+
validates :initial_failure_delay, :allow_nil => true,
|
|
202
|
+
:numericality => {:greater_than_or_equal_to => 0, :only_integer => true}
|
|
203
|
+
|
|
204
|
+
validates :repeat_failure_delay, :allow_nil => true,
|
|
205
|
+
:numericality => {:greater_than_or_equal_to => 0, :only_integer => true}
|
|
206
|
+
|
|
207
|
+
before_validation :create_ack_hash
|
|
208
|
+
validates :ack_hash, :presence => true
|
|
209
|
+
|
|
210
|
+
validates_with Flapjack::Data::Validators::IdValidator
|
|
211
|
+
|
|
212
|
+
attr_accessor :count
|
|
213
|
+
|
|
214
|
+
swagger_schema :Check do
|
|
215
|
+
key :required, [:id, :type, :name, :enabled, :initial_failure_delay,
|
|
216
|
+
:repeat_failure_delay, :failing]
|
|
217
|
+
property :id do
|
|
218
|
+
key :type, :string
|
|
219
|
+
key :format, :uuid
|
|
220
|
+
end
|
|
221
|
+
property :type do
|
|
222
|
+
key :type, :string
|
|
223
|
+
key :enum, [Flapjack::Data::Check.short_model_name.singular]
|
|
224
|
+
end
|
|
225
|
+
property :name do
|
|
226
|
+
key :type, :string
|
|
227
|
+
end
|
|
228
|
+
property :enabled do
|
|
229
|
+
key :type, :boolean
|
|
230
|
+
key :enum, [true, false]
|
|
231
|
+
end
|
|
232
|
+
property :initial_failure_delay do
|
|
233
|
+
key :type, :integer
|
|
234
|
+
end
|
|
235
|
+
property :repeat_failure_delay do
|
|
236
|
+
key :type, :integer
|
|
237
|
+
end
|
|
238
|
+
property :failing do
|
|
239
|
+
key :type, :boolean
|
|
240
|
+
key :enum, [true, false]
|
|
241
|
+
end
|
|
242
|
+
property :condition do
|
|
243
|
+
key :type, :string
|
|
244
|
+
key :enum, Flapjack::Data::Condition.healthy.keys +
|
|
245
|
+
Flapjack::Data::Condition.unhealthy.keys
|
|
246
|
+
end
|
|
247
|
+
property :ack_hash do
|
|
248
|
+
key :type, :string
|
|
249
|
+
end
|
|
250
|
+
property :relationships do
|
|
251
|
+
key :"$ref", :CheckLinks
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
swagger_schema :CheckLinks do
|
|
256
|
+
property :alerting_media do
|
|
257
|
+
key :"$ref", :MediaLinkage
|
|
258
|
+
end
|
|
259
|
+
property :contacts do
|
|
260
|
+
key :"$ref", :ContactsLinkage
|
|
261
|
+
end
|
|
262
|
+
property :current_scheduled_maintenances do
|
|
263
|
+
key :"$ref", :ScheduledMaintenancesLinkage
|
|
264
|
+
end
|
|
265
|
+
property :current_state do
|
|
266
|
+
key :"$ref", :StateLinkage
|
|
267
|
+
end
|
|
268
|
+
property :current_unscheduled_maintenance do
|
|
269
|
+
key :"$ref", :UnscheduledMaintenanceLinkage
|
|
270
|
+
end
|
|
271
|
+
property :latest_notifications do
|
|
272
|
+
key :"$ref", :StatesLinkage
|
|
273
|
+
end
|
|
274
|
+
property :scheduled_maintenances do
|
|
275
|
+
key :"$ref", :ScheduledMaintenancesLinkage
|
|
276
|
+
end
|
|
277
|
+
property :states do
|
|
278
|
+
key :"$ref", :StatesLinkage
|
|
279
|
+
end
|
|
280
|
+
property :tags do
|
|
281
|
+
key :"$ref", :TagsLinkage
|
|
282
|
+
end
|
|
283
|
+
property :unscheduled_maintenances do
|
|
284
|
+
key :"$ref", :UnscheduledMaintenancesLinkage
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
swagger_schema :CheckCreate do
|
|
289
|
+
key :required, [:type, :name, :enabled, :initial_failure_delay,
|
|
290
|
+
:repeat_failure_delay]
|
|
291
|
+
property :id do
|
|
292
|
+
key :type, :string
|
|
293
|
+
key :format, :uuid
|
|
294
|
+
end
|
|
295
|
+
property :type do
|
|
296
|
+
key :type, :string
|
|
297
|
+
key :enum, [Flapjack::Data::Check.short_model_name.singular]
|
|
298
|
+
end
|
|
299
|
+
property :name do
|
|
300
|
+
key :type, :string
|
|
301
|
+
end
|
|
302
|
+
property :enabled do
|
|
303
|
+
key :type, :boolean
|
|
304
|
+
key :enum, [true, false]
|
|
305
|
+
end
|
|
306
|
+
property :initial_failure_delay do
|
|
307
|
+
key :type, :integer
|
|
308
|
+
end
|
|
309
|
+
property :repeat_failure_delay do
|
|
310
|
+
key :type, :integer
|
|
311
|
+
end
|
|
312
|
+
property :relationships do
|
|
313
|
+
key :"$ref", :CheckCreateLinks
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
swagger_schema :CheckCreateLinks do
|
|
318
|
+
property :tags do
|
|
319
|
+
key :"$ref", :data_TagsReference
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
swagger_schema :CheckUpdate do
|
|
324
|
+
key :required, [:id, :type]
|
|
325
|
+
property :id do
|
|
326
|
+
key :type, :string
|
|
327
|
+
key :format, :uuid
|
|
328
|
+
end
|
|
329
|
+
property :type do
|
|
330
|
+
key :type, :string
|
|
331
|
+
key :enum, [Flapjack::Data::Check.short_model_name.singular]
|
|
332
|
+
end
|
|
333
|
+
property :name do
|
|
334
|
+
key :type, :string
|
|
335
|
+
end
|
|
336
|
+
property :enabled do
|
|
337
|
+
key :type, :boolean
|
|
338
|
+
key :enum, [true, false]
|
|
339
|
+
end
|
|
340
|
+
property :initial_failure_delay do
|
|
341
|
+
key :type, :integer
|
|
342
|
+
end
|
|
343
|
+
property :repeat_failure_delay do
|
|
344
|
+
key :type, :integer
|
|
345
|
+
end
|
|
346
|
+
property :relationships do
|
|
347
|
+
key :"$ref", :CheckUpdateLinks
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
swagger_schema :CheckUpdateLinks do
|
|
352
|
+
property :tags do
|
|
353
|
+
key :"$ref", :data_TagsReference
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def self.swagger_included_classes
|
|
358
|
+
# hack -- hardcoding for now
|
|
359
|
+
[
|
|
360
|
+
Flapjack::Data::Check,
|
|
361
|
+
Flapjack::Data::Contact,
|
|
362
|
+
Flapjack::Data::Medium,
|
|
363
|
+
Flapjack::Data::Rule,
|
|
364
|
+
Flapjack::Data::ScheduledMaintenance,
|
|
365
|
+
Flapjack::Data::State,
|
|
366
|
+
Flapjack::Data::Tag,
|
|
367
|
+
Flapjack::Data::UnscheduledMaintenance
|
|
368
|
+
]
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def self.jsonapi_methods
|
|
372
|
+
@jsonapi_methods ||= {
|
|
373
|
+
:post => Flapjack::Gateways::JSONAPI::Data::MethodDescriptor.new(
|
|
374
|
+
:attributes => [:name, :enabled, :initial_failure_delay,
|
|
375
|
+
:repeat_failure_delay],
|
|
376
|
+
:descriptions => {
|
|
377
|
+
:singular => "Create a check.",
|
|
378
|
+
:multiple => "Create checks."
|
|
379
|
+
}
|
|
380
|
+
),
|
|
381
|
+
:get => Flapjack::Gateways::JSONAPI::Data::MethodDescriptor.new(
|
|
382
|
+
:attributes => [:name, :enabled, :initial_failure_delay,
|
|
383
|
+
:repeat_failure_delay, :ack_hash, :failing, :condition],
|
|
384
|
+
:descriptions => {
|
|
385
|
+
:singular => "Returns data for a check.",
|
|
386
|
+
:multiple => "Returns data for multiple check records."
|
|
387
|
+
}
|
|
388
|
+
),
|
|
389
|
+
:patch => Flapjack::Gateways::JSONAPI::Data::MethodDescriptor.new(
|
|
390
|
+
:attributes => [:name, :enabled, :initial_failure_delay,
|
|
391
|
+
:repeat_failure_delay],
|
|
392
|
+
:descriptions => {
|
|
393
|
+
:singular => "Update a check.",
|
|
394
|
+
:multiple => "Update checks."
|
|
395
|
+
}
|
|
396
|
+
),
|
|
397
|
+
:delete => Flapjack::Gateways::JSONAPI::Data::MethodDescriptor.new(
|
|
398
|
+
:descriptions => {
|
|
399
|
+
:singular => "Delete a check.",
|
|
400
|
+
:multiple => "Delete checks."
|
|
401
|
+
}
|
|
402
|
+
)
|
|
403
|
+
}
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
def self.jsonapi_associations
|
|
407
|
+
unless instance_variable_defined?('@jsonapi_associations')
|
|
408
|
+
@jsonapi_associations = {
|
|
409
|
+
:alerting_media => Flapjack::Gateways::JSONAPI::Data::JoinDescriptor.new(
|
|
410
|
+
:get => true,
|
|
411
|
+
:number => :multiple, :link => true, :includable => true,
|
|
412
|
+
:type => 'medium',
|
|
413
|
+
:klass => Flapjack::Data::Medium,
|
|
414
|
+
:callback_classes => [
|
|
415
|
+
Flapjack::Data::Contact,
|
|
416
|
+
Flapjack::Data::Rule,
|
|
417
|
+
Flapjack::Data::Tag,
|
|
418
|
+
Flapjack::Data::ScheduledMaintenance
|
|
419
|
+
],
|
|
420
|
+
:descriptions => {
|
|
421
|
+
:get => "While this check is failing, returns media records " \
|
|
422
|
+
"which are receiving notifications during this failure."
|
|
423
|
+
}
|
|
424
|
+
),
|
|
425
|
+
:contacts => Flapjack::Gateways::JSONAPI::Data::JoinDescriptor.new(
|
|
426
|
+
:get => true,
|
|
427
|
+
:number => :multiple, :link => true, :includable => true,
|
|
428
|
+
:type => 'contact',
|
|
429
|
+
:klass => Flapjack::Data::Contact,
|
|
430
|
+
:callback_classes => [
|
|
431
|
+
Flapjack::Data::Rule,
|
|
432
|
+
Flapjack::Data::Tag
|
|
433
|
+
],
|
|
434
|
+
:descriptions => {
|
|
435
|
+
:get => "Returns contacts whose notification rules will " \
|
|
436
|
+
"allow them to receive notifications for events on " \
|
|
437
|
+
"this check."
|
|
438
|
+
}
|
|
439
|
+
),
|
|
440
|
+
:current_scheduled_maintenances => Flapjack::Gateways::JSONAPI::Data::JoinDescriptor.new(
|
|
441
|
+
:get => true,
|
|
442
|
+
:number => :multiple, :link => true, :includable => true,
|
|
443
|
+
:type => 'scheduled_maintenance',
|
|
444
|
+
:klass => Flapjack::Data::ScheduledMaintenance,
|
|
445
|
+
:descriptions => {
|
|
446
|
+
:get => "Returns scheduled maintenance periods currently in " \
|
|
447
|
+
" effect for this check."
|
|
448
|
+
}
|
|
449
|
+
),
|
|
450
|
+
:current_state => Flapjack::Gateways::JSONAPI::Data::JoinDescriptor.new(
|
|
451
|
+
:get => true,
|
|
452
|
+
:number => :singular, :link => true, :includable => true,
|
|
453
|
+
:descriptions => {
|
|
454
|
+
:get => "Returns the current State record for this check."
|
|
455
|
+
}
|
|
456
|
+
),
|
|
457
|
+
:current_unscheduled_maintenance => Flapjack::Gateways::JSONAPI::Data::JoinDescriptor.new(
|
|
458
|
+
:get => true,
|
|
459
|
+
:number => :singular, :link => true, :includable => true,
|
|
460
|
+
:type => 'unscheduled_maintenance',
|
|
461
|
+
:klass => Flapjack::Data::UnscheduledMaintenance,
|
|
462
|
+
:descriptions => {
|
|
463
|
+
:get => "If the check is currently acknowledged, returns the " \
|
|
464
|
+
"unscheduled maintenance period created for that."
|
|
465
|
+
}
|
|
466
|
+
),
|
|
467
|
+
:latest_notifications => Flapjack::Gateways::JSONAPI::Data::JoinDescriptor.new(
|
|
468
|
+
:get => true,
|
|
469
|
+
:number => :multiple, :link => true, :includable => true,
|
|
470
|
+
:descriptions => {
|
|
471
|
+
:get => "Returns the most recent State records for each " \
|
|
472
|
+
"problem condition that produced notifications."
|
|
473
|
+
}
|
|
474
|
+
),
|
|
475
|
+
:scheduled_maintenances => Flapjack::Gateways::JSONAPI::Data::JoinDescriptor.new(
|
|
476
|
+
:get => true,
|
|
477
|
+
:number => :multiple, :link => true, :includable => false,
|
|
478
|
+
:descriptions => {
|
|
479
|
+
:get => "Returns all scheduled maintenance periods for the " \
|
|
480
|
+
"check; default sort order is newest first."
|
|
481
|
+
}
|
|
482
|
+
),
|
|
483
|
+
:states => Flapjack::Gateways::JSONAPI::Data::JoinDescriptor.new(
|
|
484
|
+
:get => true,
|
|
485
|
+
:number => :multiple, :link => true, :includable => false,
|
|
486
|
+
:descriptions => {
|
|
487
|
+
:get => "Returns all state records for the check; default " \
|
|
488
|
+
"sort order is newest first."
|
|
489
|
+
}
|
|
490
|
+
),
|
|
491
|
+
:tags => Flapjack::Gateways::JSONAPI::Data::JoinDescriptor.new(
|
|
492
|
+
:post => true, :get => true, :patch => true, :delete => true,
|
|
493
|
+
:number => :multiple, :link => true, :includable => true,
|
|
494
|
+
:descriptions => {
|
|
495
|
+
:post => "Associate tags with this check.",
|
|
496
|
+
:get => "Returns all tags linked to this check.",
|
|
497
|
+
:patch => "Update the tags associated with this check.",
|
|
498
|
+
:delete => "Delete associations between tags and this check."
|
|
499
|
+
}
|
|
500
|
+
),
|
|
501
|
+
:unscheduled_maintenances => Flapjack::Gateways::JSONAPI::Data::JoinDescriptor.new(
|
|
502
|
+
:get => true,
|
|
503
|
+
:number => :multiple, :link => true, :includable => false,
|
|
504
|
+
:descriptions => {
|
|
505
|
+
:get => "Returns all unscheduled maintenance periods for the " \
|
|
506
|
+
"check; default sort order is newest first."
|
|
507
|
+
}
|
|
508
|
+
)
|
|
509
|
+
}
|
|
510
|
+
populate_association_data(@jsonapi_associations)
|
|
511
|
+
end
|
|
512
|
+
@jsonapi_associations
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
def in_scheduled_maintenance?(t = Time.now)
|
|
516
|
+
!scheduled_maintenances_at(t).empty?
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
def current_scheduled_maintenances
|
|
520
|
+
scheduled_maintenances_at(Time.now)
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
def in_unscheduled_maintenance?(t = Time.now)
|
|
524
|
+
!unscheduled_maintenances_at(t).empty?
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
def current_unscheduled_maintenance
|
|
528
|
+
unscheduled_maintenances_at(Time.now).all.first
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
# TODO allow summary to be changed as part of the termination
|
|
532
|
+
def end_scheduled_maintenance(sched_maint, at_time)
|
|
533
|
+
at_time = Time.at(at_time) unless at_time.is_a?(Time)
|
|
534
|
+
|
|
535
|
+
if sched_maint.start_time >= at_time
|
|
536
|
+
# the scheduled maintenance period is in the future
|
|
537
|
+
self.scheduled_maintenances.remove(sched_maint)
|
|
538
|
+
sched_maint.destroy
|
|
539
|
+
return true
|
|
540
|
+
elsif sched_maint.end_time >= at_time
|
|
541
|
+
# it spans the current time, so we'll stop it at that point
|
|
542
|
+
sched_maint.end_time = at_time
|
|
543
|
+
sched_maint.save
|
|
544
|
+
return true
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
false
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
def set_unscheduled_maintenance(unsched_maint, options = {})
|
|
551
|
+
current_time = Time.now
|
|
552
|
+
|
|
553
|
+
self.class.lock(Flapjack::Data::UnscheduledMaintenance,
|
|
554
|
+
Flapjack::Data::State) do
|
|
555
|
+
|
|
556
|
+
self.alertable = false
|
|
557
|
+
self.save!
|
|
558
|
+
|
|
559
|
+
# time_remaining
|
|
560
|
+
if (unsched_maint.end_time - current_time) > 0
|
|
561
|
+
self.clear_unscheduled_maintenance(unsched_maint.start_time)
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
self.unscheduled_maintenances << unsched_maint
|
|
565
|
+
end
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
def clear_unscheduled_maintenance(end_time)
|
|
569
|
+
Flapjack::Data::UnscheduledMaintenance.lock do
|
|
570
|
+
t = Time.now
|
|
571
|
+
start_range = Zermelo::Filters::IndexRange.new(nil, t, :by_score => true)
|
|
572
|
+
end_range = Zermelo::Filters::IndexRange.new(t, nil, :by_score => true)
|
|
573
|
+
unsched_maints = self.unscheduled_maintenances.intersect(:start_time => start_range,
|
|
574
|
+
:end_time => end_range)
|
|
575
|
+
unsched_maints_count = unsched_maints.empty?
|
|
576
|
+
unless unsched_maints_count == 0
|
|
577
|
+
# FIXME log warning if count > 1
|
|
578
|
+
unsched_maints.each do |usm|
|
|
579
|
+
usm.end_time = end_time
|
|
580
|
+
usm.save
|
|
581
|
+
end
|
|
582
|
+
end
|
|
583
|
+
end
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
private
|
|
587
|
+
|
|
588
|
+
# would need to be "#{entity.name}:#{name}" to be compatible with v1, but
|
|
589
|
+
# to support name changes it must be something invariant
|
|
590
|
+
def create_ack_hash
|
|
591
|
+
return unless self.ack_hash.nil? # :on => :create isn't working
|
|
592
|
+
self.id = self.class.generate_id if self.id.nil?
|
|
593
|
+
self.ack_hash = Digest.hexencode(Digest::SHA1.new.digest(self.id))[0..7].downcase
|
|
594
|
+
end
|
|
595
|
+
|
|
596
|
+
def scheduled_maintenances_at(t)
|
|
597
|
+
start_range = Zermelo::Filters::IndexRange.new(nil, t, :by_score => true)
|
|
598
|
+
end_range = Zermelo::Filters::IndexRange.new(t, nil, :by_score => true)
|
|
599
|
+
self.scheduled_maintenances.intersect(:start_time => start_range,
|
|
600
|
+
:end_time => end_range)
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
def unscheduled_maintenances_at(t)
|
|
604
|
+
start_range = Zermelo::Filters::IndexRange.new(nil, t, :by_score => true)
|
|
605
|
+
end_range = Zermelo::Filters::IndexRange.new(t, nil, :by_score => true)
|
|
606
|
+
self.unscheduled_maintenances.intersect(:start_time => start_range,
|
|
607
|
+
:end_time => end_range)
|
|
608
|
+
end
|
|
609
|
+
end
|
|
610
|
+
end
|
|
611
|
+
end
|