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,56 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# 'Notification' refers to the template object created when an event occurs,
|
4
|
-
# from which individual 'Message' objects are created, one for each
|
5
|
-
# contact+media recipient.
|
6
|
-
|
7
|
-
require 'flapjack/data/contact'
|
8
|
-
|
9
|
-
module Flapjack
|
10
|
-
module Data
|
11
|
-
class Message
|
12
|
-
|
13
|
-
attr_reader :medium, :address, :duration, :contact, :rollup
|
14
|
-
|
15
|
-
def self.for_contact(contact, opts = {})
|
16
|
-
self.new(:contact => contact,
|
17
|
-
:medium => opts[:medium],
|
18
|
-
:address => opts[:address],
|
19
|
-
:duration => opts[:duration],
|
20
|
-
:rollup => opts[:rollup])
|
21
|
-
end
|
22
|
-
|
23
|
-
def id
|
24
|
-
return @id if @id
|
25
|
-
t = Time.now
|
26
|
-
# FIXME: consider using a UUID here
|
27
|
-
# this is planned to be used as part of alert history keys
|
28
|
-
@id = "#{self.object_id.to_i}-#{t.to_i}.#{t.tv_usec}"
|
29
|
-
end
|
30
|
-
|
31
|
-
def contents
|
32
|
-
c = {'media' => medium,
|
33
|
-
'address' => address,
|
34
|
-
'id' => id,
|
35
|
-
'rollup' => rollup,
|
36
|
-
'contact_id' => contact.id,
|
37
|
-
'contact_first_name' => contact.first_name,
|
38
|
-
'contact_last_name' => contact.last_name}
|
39
|
-
c['duration'] = duration if duration
|
40
|
-
c
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
def initialize(opts = {})
|
46
|
-
@contact = opts[:contact]
|
47
|
-
@medium = opts[:medium]
|
48
|
-
@address = opts[:address]
|
49
|
-
@duration = opts[:duration]
|
50
|
-
@rollup = opts[:rollup]
|
51
|
-
end
|
52
|
-
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
@@ -1,234 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'flapjack/data/contact'
|
4
|
-
require 'flapjack/data/entity_check'
|
5
|
-
|
6
|
-
require 'flapjack/data/semaphore'
|
7
|
-
|
8
|
-
module Flapjack
|
9
|
-
module Data
|
10
|
-
class Migration
|
11
|
-
|
12
|
-
ENTITY_DATA_MIGRATION = 'entity_data_migration'
|
13
|
-
|
14
|
-
# copied from jsonapi/contact_methods.rb, could extract both into separate file
|
15
|
-
def self.obtain_semaphore(resource, description, options = {})
|
16
|
-
raise "Redis connection not set" unless redis = options[:redis]
|
17
|
-
|
18
|
-
logger = options[:logger]
|
19
|
-
|
20
|
-
semaphore = nil
|
21
|
-
strikes = 0
|
22
|
-
begin
|
23
|
-
semaphore = Flapjack::Data::Semaphore.new(resource, :redis => redis, :expiry => 300)
|
24
|
-
rescue Flapjack::Data::Semaphore::ResourceLocked
|
25
|
-
strikes += 1
|
26
|
-
if strikes < 10
|
27
|
-
sleep 2
|
28
|
-
retry
|
29
|
-
end
|
30
|
-
sempahore = nil
|
31
|
-
end
|
32
|
-
|
33
|
-
if semaphore.nil?
|
34
|
-
unless logger.nil?
|
35
|
-
logger.fatal "Could not obtain lock for data migration (#{reason}). Ensure that " +
|
36
|
-
"no other flapjack processes are running that might be executing " +
|
37
|
-
"migrations, check logs for any exceptions, manually delete the " +
|
38
|
-
"'#{resource}' key from your Flapjack Redis " +
|
39
|
-
"database and try running Flapjack again."
|
40
|
-
end
|
41
|
-
raise "Unable to obtain semaphore #{resource}"
|
42
|
-
end
|
43
|
-
|
44
|
-
semaphore
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.create_entity_ids_if_required(options = {})
|
48
|
-
raise "Redis connection not set" unless redis = options[:redis]
|
49
|
-
|
50
|
-
logger = options[:logger]
|
51
|
-
|
52
|
-
return if redis.exists('created_ids_for_old_entities_without_ids')
|
53
|
-
|
54
|
-
semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, 'entity id creation',
|
55
|
-
:redis => redis, :logger => logger)
|
56
|
-
|
57
|
-
begin
|
58
|
-
logger.warn "Ensuring all entities have ids ..." unless logger.nil?
|
59
|
-
|
60
|
-
Flapjack::Data::EntityCheck.find_current_names_by_entity(:redis => redis, :logger => logger).keys.each {|entity_name|
|
61
|
-
entity = Flapjack::Data::Entity.find_by_name(entity_name, :create => true, :redis => redis, :logger => logger)
|
62
|
-
}
|
63
|
-
|
64
|
-
all_checks = Flapjack::Data::EntityCheck.all(:redis => redis, :logger => logger, :create_entity => true)
|
65
|
-
|
66
|
-
redis.set('created_ids_for_old_entities_without_ids', 'true')
|
67
|
-
logger.warn "Entity id creation complete."
|
68
|
-
ensure
|
69
|
-
semaphore.release
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.migrate_entity_check_data_if_required(options = {})
|
74
|
-
raise "Redis connection not set" unless redis = options[:redis]
|
75
|
-
|
76
|
-
logger = options[:logger]
|
77
|
-
|
78
|
-
return if redis.exists('all_checks')
|
79
|
-
|
80
|
-
semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, 'entity check data',
|
81
|
-
:redis => redis, :logger => logger)
|
82
|
-
|
83
|
-
begin
|
84
|
-
check_names = redis.keys('check:*').map {|c| c.sub(/^check:/, '') } |
|
85
|
-
Flapjack::Data::EntityCheck.find_current_names(:redis => redis)
|
86
|
-
|
87
|
-
unless check_names.empty?
|
88
|
-
logger.warn "Upgrading Flapjack's entity/check Redis indexes..." unless logger.nil?
|
89
|
-
|
90
|
-
timestamp = Time.now.to_i
|
91
|
-
|
92
|
-
check_names.each do |ecn|
|
93
|
-
redis.zadd("all_checks", timestamp, ecn)
|
94
|
-
entity_name, check = ecn.split(':', 2)
|
95
|
-
redis.zadd("all_checks:#{entity_name}", timestamp, check)
|
96
|
-
# not deleting the check hashes, they store useful data
|
97
|
-
end
|
98
|
-
logger.warn "Checks indexed." unless logger.nil?
|
99
|
-
end
|
100
|
-
|
101
|
-
entity_name_keys = redis.keys("entity_id:*")
|
102
|
-
unless entity_name_keys.empty?
|
103
|
-
ids = redis.mget(*entity_name_keys)
|
104
|
-
|
105
|
-
entity_name_keys.each do |enk|
|
106
|
-
enk =~ /^entity_id:(.+)$/; entity_name = $1; entity_id = ids.shift
|
107
|
-
|
108
|
-
redis.hset('all_entity_names_by_id', entity_id, entity_name)
|
109
|
-
redis.hset('all_entity_ids_by_name', entity_name, entity_id)
|
110
|
-
|
111
|
-
redis.del(enk)
|
112
|
-
redis.del("entity:#{entity_id}")
|
113
|
-
end
|
114
|
-
logger.warn "Entities indexed." unless logger.nil?
|
115
|
-
end
|
116
|
-
|
117
|
-
logger.warn "Indexing complete." unless logger.nil? || (check_names.empty? && entity_name_keys.empty?)
|
118
|
-
ensure
|
119
|
-
semaphore.release
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
def self.clear_orphaned_entity_ids(options = {})
|
124
|
-
raise "Redis connection not set" unless redis = options[:redis]
|
125
|
-
|
126
|
-
logger = options[:logger]
|
127
|
-
|
128
|
-
semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION,
|
129
|
-
'orphaned entity ids', :redis => redis, :logger => logger)
|
130
|
-
|
131
|
-
begin
|
132
|
-
logger.info "Checking for orphaned entity ids..." unless logger.nil?
|
133
|
-
|
134
|
-
valid_entity_data = redis.hgetall('all_entity_ids_by_name')
|
135
|
-
|
136
|
-
missing_ids = redis.hgetall('all_entity_names_by_id').reject {|e_id, e_name|
|
137
|
-
valid_entity_data[e_name] == e_id
|
138
|
-
}
|
139
|
-
|
140
|
-
unless missing_ids.empty?
|
141
|
-
logger.info "Clearing ids (#{missing_ids.inspect})" unless logger.nil?
|
142
|
-
redis.hdel('all_entity_names_by_id', missing_ids.keys)
|
143
|
-
end
|
144
|
-
ensure
|
145
|
-
semaphore.release
|
146
|
-
logger.info "Finished checking for orphaned entity ids." unless logger.nil?
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def self.refresh_archive_index(options = {})
|
151
|
-
raise "Redis connection not set" unless redis = options[:redis]
|
152
|
-
archive_keys = redis.keys('events_archive:*')
|
153
|
-
if archive_keys.empty?
|
154
|
-
redis.del('known_events_archive_keys')
|
155
|
-
return
|
156
|
-
end
|
157
|
-
|
158
|
-
grouped_keys = archive_keys.group_by do |ak|
|
159
|
-
(redis.llen(ak) > 0) ? 'add' : 'remove'
|
160
|
-
end
|
161
|
-
|
162
|
-
{'remove' => :srem, 'add' => :sadd}.each_pair do |k, cmd|
|
163
|
-
next unless grouped_keys.has_key?(k) && !grouped_keys[k].empty?
|
164
|
-
redis.send(cmd, 'known_events_archive_keys', grouped_keys[k])
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
def self.purge_expired_archive_index(options = {})
|
169
|
-
raise "Redis connection not set" unless redis = options[:redis]
|
170
|
-
return unless redis.exists('known_events_archive_keys')
|
171
|
-
|
172
|
-
redis.smembers('known_events_archive_keys').each do |ak|
|
173
|
-
redis.srem('known_events_archive_keys', ak) unless redis.exists(ak)
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
def self.correct_notification_rule_contact_linkages(options = {})
|
178
|
-
raise "Redis connection not set" unless redis = options[:redis]
|
179
|
-
|
180
|
-
logger = options[:logger]
|
181
|
-
|
182
|
-
return if redis.exists('corrected_notification_rule_contact_linkages')
|
183
|
-
|
184
|
-
invalid_notification_rule_keys = redis.keys("notification_rule:*").select {|k|
|
185
|
-
contact_id = redis.hget(k, 'contact_id')
|
186
|
-
contact_id.nil? || contact_id.empty?
|
187
|
-
}.collect {|nrk| nrk.sub(/^notification_rule:/, '') }
|
188
|
-
|
189
|
-
unless invalid_notification_rule_keys.empty?
|
190
|
-
Flapjack::Data::Contact.all(:redis => redis).each do |contact|
|
191
|
-
correctable = contact.notification_rule_ids & invalid_notification_rule_keys
|
192
|
-
next if correctable.empty?
|
193
|
-
correctable.each {|ck| redis.hset("notification_rule:#{ck}", 'contact_id', contact.id) }
|
194
|
-
logger.warn "Set contact #{contact.id} for rules #{correctable.join(', ')}" unless logger.nil?
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
redis.set('corrected_notification_rule_contact_linkages', 'true')
|
199
|
-
end
|
200
|
-
|
201
|
-
def self.validate_scheduled_maintenance_periods(options = {})
|
202
|
-
raise "Redis connection not set" unless redis = options[:redis]
|
203
|
-
|
204
|
-
logger = options[:logger]
|
205
|
-
|
206
|
-
return if redis.exists('validated_scheduled_maintenance_periods')
|
207
|
-
|
208
|
-
Flapjack::Data::EntityCheck.all(:redis => redis).compact.select {|ec|
|
209
|
-
ec.in_scheduled_maintenance?
|
210
|
-
}.each do |check|
|
211
|
-
check.update_current_scheduled_maintenance(:revalidate => true)
|
212
|
-
end
|
213
|
-
|
214
|
-
logger.warn "Validated scheduled maintenance period expiry" unless logger.nil?
|
215
|
-
redis.set('validated_scheduled_maintenance_periods', 'true')
|
216
|
-
end
|
217
|
-
|
218
|
-
def self.correct_rollup_including_disabled_checks(options = {})
|
219
|
-
raise "Redis connection not set" unless redis = options[:redis]
|
220
|
-
logger = options[:logger]
|
221
|
-
return if redis.exists('corrected_rollup_including_disabled_checks')
|
222
|
-
|
223
|
-
Flapjack::Data::Contact.all(:redis => redis).each do |contact|
|
224
|
-
contact.media_list.each do |medium|
|
225
|
-
contact.clean_alerting_checks_for_media(medium)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
logger.warn "Corrected rollup to no longer include disabled checks" unless logger.nil?
|
230
|
-
redis.set('corrected_rollup_including_disabled_checks', 'true')
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|
234
|
-
end
|
@@ -1,425 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'active_support/time'
|
4
|
-
require 'ice_cube'
|
5
|
-
require 'flapjack/utility'
|
6
|
-
|
7
|
-
module Flapjack
|
8
|
-
module Data
|
9
|
-
class NotificationRule
|
10
|
-
|
11
|
-
extend Flapjack::Utility
|
12
|
-
|
13
|
-
attr_accessor :id, :contact_id, :entities, :regex_entities, :tags, :regex_tags,
|
14
|
-
:time_restrictions, :unknown_media, :warning_media, :critical_media,
|
15
|
-
:unknown_blackhole, :warning_blackhole, :critical_blackhole
|
16
|
-
|
17
|
-
def self.all(options = {})
|
18
|
-
raise "Redis connection not set" unless redis = options[:redis]
|
19
|
-
redis.keys("contact_notification_rules:*").inject([]) do |memo, contact_key|
|
20
|
-
redis.smembers(contact_key).each do |rule_id|
|
21
|
-
ret = self.find_by_id(rule_id, :redis => redis)
|
22
|
-
memo << ret unless ret.nil?
|
23
|
-
end
|
24
|
-
memo
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.exists_with_id?(rule_id, options = {})
|
29
|
-
raise "Redis connection not set" unless redis = options[:redis]
|
30
|
-
raise "No id value passed" unless not (rule_id.nil? || rule_id == '')
|
31
|
-
redis.exists("notification_rule:#{rule_id}")
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.find_by_id(rule_id, options = {})
|
35
|
-
raise "Redis connection not set" unless redis = options[:redis]
|
36
|
-
raise "No id value passed" unless not (rule_id.nil? || rule_id == '')
|
37
|
-
|
38
|
-
# sanity check
|
39
|
-
return unless redis.exists("notification_rule:#{rule_id}")
|
40
|
-
|
41
|
-
self.new({:id => rule_id.to_s}, {:redis => redis})
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.find_by_ids(rule_ids, options = {})
|
45
|
-
raise "Redis connection not set" unless redis = options[:redis]
|
46
|
-
|
47
|
-
rule_ids.map do |id|
|
48
|
-
self.find_by_id(id, options)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# replacing save! etc
|
53
|
-
def self.add(rule_data, options = {})
|
54
|
-
raise "Redis connection not set" unless redis = options[:redis]
|
55
|
-
|
56
|
-
if rule_data[:id] && self.find_by_id(rule_data[:id], :redis => redis)
|
57
|
-
errors = ["a notification rule already exists with id '#{rule_data[:id]}'"]
|
58
|
-
return errors
|
59
|
-
end
|
60
|
-
rule_id = rule_data[:id] || SecureRandom.uuid
|
61
|
-
|
62
|
-
errors = self.add_or_update(rule_data.merge(:id => rule_id), :redis => redis, :logger => options[:logger])
|
63
|
-
return errors unless errors.nil? || errors.empty?
|
64
|
-
|
65
|
-
self.find_by_id(rule_id, :redis => redis)
|
66
|
-
end
|
67
|
-
|
68
|
-
def update(update_data, opts = {})
|
69
|
-
[:entities, :regex_entities, :tags, :regex_tags,
|
70
|
-
:time_restrictions, :unknown_media, :warning_media, :critical_media,
|
71
|
-
:unknown_blackhole, :warning_blackhole, :critical_blackhole].each do |update_key|
|
72
|
-
|
73
|
-
next if update_data.has_key?(update_key)
|
74
|
-
update_data[update_key] = self.send(update_key)
|
75
|
-
end
|
76
|
-
|
77
|
-
update_data.update(:id => @id, :contact_id => @contact_id)
|
78
|
-
errors = self.class.add_or_update(update_data, :redis => @redis, :logger => opts[:logger])
|
79
|
-
return errors unless errors.nil? || errors.empty?
|
80
|
-
|
81
|
-
refresh
|
82
|
-
nil
|
83
|
-
end
|
84
|
-
|
85
|
-
# NB: ice_cube doesn't have much rule data validation, and has
|
86
|
-
# problems with infinite loops if the data can't logically match; see
|
87
|
-
# https://github.com/seejohnrun/ice_cube/issues/127 &
|
88
|
-
# https://github.com/seejohnrun/ice_cube/issues/137
|
89
|
-
# We may want to consider some sort of timeout-based check around
|
90
|
-
# anything that could fall into that.
|
91
|
-
#
|
92
|
-
# We don't want to replicate IceCube's from_hash behaviour here,
|
93
|
-
# but we do need to apply some sanity checking on the passed data.
|
94
|
-
def self.time_restriction_to_icecube_schedule(tr, timezone, opts = {})
|
95
|
-
return if tr.nil? || !tr.is_a?(Hash) ||
|
96
|
-
timezone.nil? || !timezone.is_a?(ActiveSupport::TimeZone)
|
97
|
-
prepared_restrictions = prepare_time_restriction(tr, timezone)
|
98
|
-
return if prepared_restrictions.nil?
|
99
|
-
IceCube::Schedule.from_hash(prepared_restrictions)
|
100
|
-
rescue ArgumentError => ae
|
101
|
-
if logger = opts[:logger]
|
102
|
-
logger.error "Couldn't parse rule data #{e.class}: #{e.message}"
|
103
|
-
logger.error prepared_restrictions.inspect
|
104
|
-
logger.error e.backtrace.join("\n")
|
105
|
-
end
|
106
|
-
nil
|
107
|
-
end
|
108
|
-
|
109
|
-
def to_jsonapi(opts = {})
|
110
|
-
json_data = self.class.hashify(:id, :tags, :regex_tags, :entities, :regex_entities,
|
111
|
-
:time_restrictions, :unknown_media, :warning_media, :critical_media,
|
112
|
-
:unknown_blackhole, :warning_blackhole, :critical_blackhole) {|k|
|
113
|
-
case k
|
114
|
-
when :tags, :regex_tags
|
115
|
-
[k.to_s, self.send(k).to_a.sort]
|
116
|
-
else
|
117
|
-
[k.to_s, self.send(k)]
|
118
|
-
end
|
119
|
-
}.merge('links' => {'contacts' => [self.contact_id]})
|
120
|
-
|
121
|
-
Flapjack.dump_json(json_data)
|
122
|
-
end
|
123
|
-
|
124
|
-
# If the rule has any entities, then one of them must match the event's entity
|
125
|
-
def match_entity?(event_id)
|
126
|
-
return true unless @entities && @entities.length > 0
|
127
|
-
event_entity = event_id.split(':').first
|
128
|
-
@entities.include?(event_entity)
|
129
|
-
end
|
130
|
-
|
131
|
-
# If the rule has any regex_entities, then all of them must match the
|
132
|
-
# event's entity
|
133
|
-
def match_regex_entities?(event_id)
|
134
|
-
return true unless @regex_entities && @regex_entities.length > 0
|
135
|
-
event_entity = event_id.split(':').first
|
136
|
-
matches = 0
|
137
|
-
@regex_entities.each do |regex_entity|
|
138
|
-
matches += 1 if /#{regex_entity}/ === event_entity
|
139
|
-
end
|
140
|
-
matches >= @regex_entities.length
|
141
|
-
end
|
142
|
-
|
143
|
-
# If the rule has any tags, then they must all be present in the
|
144
|
-
# event's tags
|
145
|
-
def match_tags?(event_tags)
|
146
|
-
return true unless @tags && @tags.length > 0
|
147
|
-
@tags.subset?(event_tags)
|
148
|
-
end
|
149
|
-
|
150
|
-
# If the rule has any regex_tags, then they must all match at least
|
151
|
-
# one of the event's tags
|
152
|
-
def match_regex_tags?(event_tags)
|
153
|
-
return true unless @regex_tags && @regex_tags.length > 0
|
154
|
-
matches = 0
|
155
|
-
@regex_tags.each do |regex_tag|
|
156
|
-
matches += 1 if event_tags.any? { |event_tag| /#{regex_tag}/ === event_tag }
|
157
|
-
end
|
158
|
-
matches >= @regex_tags.length
|
159
|
-
end
|
160
|
-
|
161
|
-
def blackhole?(severity)
|
162
|
-
('unknown'.eql?(severity.downcase) && @unknown_blackhole) ||
|
163
|
-
('warning'.eql?(severity.downcase) && @warning_blackhole) ||
|
164
|
-
('critical'.eql?(severity.downcase) && @critical_blackhole)
|
165
|
-
end
|
166
|
-
|
167
|
-
def media_for_severity(severity)
|
168
|
-
case severity
|
169
|
-
when 'unknown'
|
170
|
-
@unknown_media
|
171
|
-
when 'warning'
|
172
|
-
@warning_media
|
173
|
-
when 'critical'
|
174
|
-
@critical_media
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def is_specific?
|
179
|
-
(!@entities.nil? && !@entities.empty?) ||
|
180
|
-
(!@regex_entities.nil? && !@regex_entities.empty?) ||
|
181
|
-
(!@tags.nil? && !@tags.empty?) ||
|
182
|
-
(!@regex_tags.nil? && !@regex_tags.empty?)
|
183
|
-
end
|
184
|
-
|
185
|
-
private
|
186
|
-
|
187
|
-
def initialize(rule_data, opts = {})
|
188
|
-
@redis ||= opts[:redis]
|
189
|
-
raise "a redis connection must be supplied" unless @redis
|
190
|
-
@logger = opts[:logger]
|
191
|
-
@id = rule_data[:id]
|
192
|
-
refresh
|
193
|
-
end
|
194
|
-
|
195
|
-
def self.prevalidate_data(rule_data, options = {})
|
196
|
-
errors = self.validate_data(preen(rule_data), options.merge(:id_not_required => true))
|
197
|
-
end
|
198
|
-
|
199
|
-
def self.preen(rule_data)
|
200
|
-
# make some assumptions about the incoming data
|
201
|
-
rule_data[:unknown_blackhole] = rule_data[:unknown_blackhole] || false
|
202
|
-
rule_data[:warning_blackhole] = rule_data[:warning_blackhole] || false
|
203
|
-
rule_data[:critical_blackhole] = rule_data[:critical_blackhole] || false
|
204
|
-
if rule_data[:tags].is_a?(Array)
|
205
|
-
rule_data[:tags] = Set.new(rule_data[:tags])
|
206
|
-
end
|
207
|
-
if rule_data[:regex_tags].is_a?(Array)
|
208
|
-
rule_data[:regex_tags] = Set.new(rule_data[:regex_tags])
|
209
|
-
end
|
210
|
-
rule_data
|
211
|
-
end
|
212
|
-
|
213
|
-
def self.add_or_update(rule_data, options = {})
|
214
|
-
redis = options[:redis]
|
215
|
-
raise "a redis connection must be supplied" unless redis
|
216
|
-
logger = options[:logger]
|
217
|
-
|
218
|
-
rule_data = preen(rule_data)
|
219
|
-
errors = self.validate_data(rule_data, options)
|
220
|
-
return errors unless errors.nil? || errors.empty?
|
221
|
-
|
222
|
-
# whitelisting fields, rather than passing through submitted data directly
|
223
|
-
tag_data = rule_data[:tags].is_a?(Set) ? rule_data[:tags].to_a : nil
|
224
|
-
regex_tag_data = rule_data[:regex_tags].is_a?(Set) ? rule_data[:regex_tags].to_a : nil
|
225
|
-
|
226
|
-
json_rule_data = {
|
227
|
-
:id => rule_data[:id].to_s,
|
228
|
-
:contact_id => rule_data[:contact_id].to_s,
|
229
|
-
:entities => Flapjack.dump_json(rule_data[:entities]),
|
230
|
-
:regex_entities => Flapjack.dump_json(rule_data[:regex_entities]),
|
231
|
-
:tags => Flapjack.dump_json(tag_data),
|
232
|
-
:regex_tags => Flapjack.dump_json(regex_tag_data),
|
233
|
-
:time_restrictions => Flapjack.dump_json(rule_data[:time_restrictions]),
|
234
|
-
:unknown_media => Flapjack.dump_json(rule_data[:unknown_media]),
|
235
|
-
:warning_media => Flapjack.dump_json(rule_data[:warning_media]),
|
236
|
-
:critical_media => Flapjack.dump_json(rule_data[:critical_media]),
|
237
|
-
:unknown_blackhole => rule_data[:unknown_blackhole],
|
238
|
-
:warning_blackhole => rule_data[:warning_blackhole],
|
239
|
-
:critical_blackhole => rule_data[:critical_blackhole],
|
240
|
-
}
|
241
|
-
|
242
|
-
logger.debug("NotificationRule#add_or_update json_rule_data: #{json_rule_data.inspect}") if logger
|
243
|
-
|
244
|
-
redis.sadd("contact_notification_rules:#{json_rule_data[:contact_id]}",
|
245
|
-
json_rule_data[:id])
|
246
|
-
redis.hmset("notification_rule:#{json_rule_data[:id]}",
|
247
|
-
*json_rule_data.flatten)
|
248
|
-
nil
|
249
|
-
end
|
250
|
-
|
251
|
-
def self.prepare_time_restriction(time_restriction, timezone = nil)
|
252
|
-
# this will hand back a 'deep' copy
|
253
|
-
tr = symbolize(time_restriction)
|
254
|
-
|
255
|
-
return unless (tr.has_key?(:start_time) || tr.has_key?(:start_date)) &&
|
256
|
-
(tr.has_key?(:end_time) || tr.has_key?(:end_date))
|
257
|
-
|
258
|
-
# exrules is deprecated in latest ice_cube, but may be stored in data
|
259
|
-
# serialised from earlier versions of the gem
|
260
|
-
# ( https://github.com/flapjack/flapjack/issues/715 )
|
261
|
-
tr.delete(:exrules)
|
262
|
-
|
263
|
-
parsed_time = proc {|tr, field|
|
264
|
-
if t = tr.delete(field)
|
265
|
-
t = t.dup
|
266
|
-
t = t[:time] if t.is_a?(Hash)
|
267
|
-
|
268
|
-
if t.is_a?(Time)
|
269
|
-
t
|
270
|
-
else
|
271
|
-
begin; (timezone || Time).parse(t); rescue ArgumentError; nil; end
|
272
|
-
end
|
273
|
-
else
|
274
|
-
nil
|
275
|
-
end
|
276
|
-
}
|
277
|
-
|
278
|
-
start_time = parsed_time.call(tr, :start_date) || parsed_time.call(tr, :start_time)
|
279
|
-
end_time = parsed_time.call(tr, :end_date) || parsed_time.call(tr, :end_time)
|
280
|
-
|
281
|
-
return unless start_time && end_time
|
282
|
-
|
283
|
-
tr[:start_time] = timezone ?
|
284
|
-
{:time => start_time, :zone => timezone.name} :
|
285
|
-
start_time
|
286
|
-
|
287
|
-
tr[:end_time] = timezone ?
|
288
|
-
{:time => end_time, :zone => timezone.name} :
|
289
|
-
end_time
|
290
|
-
|
291
|
-
tr[:duration] = end_time - start_time
|
292
|
-
|
293
|
-
# check that rrule types are valid IceCube rule types
|
294
|
-
return unless tr[:rrules].is_a?(Array) &&
|
295
|
-
tr[:rrules].all? {|rr| rr.is_a?(Hash)} &&
|
296
|
-
(tr[:rrules].map {|rr| rr[:rule_type]} -
|
297
|
-
['Daily', 'Hourly', 'Minutely', 'Monthly', 'Secondly',
|
298
|
-
'Weekly', 'Yearly']).empty?
|
299
|
-
|
300
|
-
# rewrite Weekly to IceCube::WeeklyRule, etc
|
301
|
-
tr[:rrules].each {|rrule|
|
302
|
-
rrule[:rule_type] = "IceCube::#{rrule[:rule_type]}Rule"
|
303
|
-
}
|
304
|
-
|
305
|
-
# TODO does this need to check classes for the following values?
|
306
|
-
# "validations": {
|
307
|
-
# "day": [1,2,3,4,5]
|
308
|
-
# },
|
309
|
-
# "interval": 1,
|
310
|
-
# "week_start": 0
|
311
|
-
|
312
|
-
tr
|
313
|
-
end
|
314
|
-
|
315
|
-
VALIDATION_PROCS = {
|
316
|
-
proc {|d| !d.has_key?(:entities) ||
|
317
|
-
( d[:entities].nil? ||
|
318
|
-
d[:entities].is_a?(Array) &&
|
319
|
-
d[:entities].all? {|e| e.is_a?(String)} ) } =>
|
320
|
-
"entities must be a list of strings",
|
321
|
-
|
322
|
-
proc {|d| !d.has_key?(:regex_entities) ||
|
323
|
-
( d[:regex_entities].nil? ||
|
324
|
-
d[:regex_entities].is_a?(Array) &&
|
325
|
-
d[:regex_entities].all? {|e| e.is_a?(String)} ) } =>
|
326
|
-
"regex_entities must be a list of strings",
|
327
|
-
|
328
|
-
proc {|d| !d.has_key?(:tags) ||
|
329
|
-
( d[:tags].nil? ||
|
330
|
-
d[:tags].is_a?(Set) &&
|
331
|
-
d[:tags].all? {|et| et.is_a?(String)} ) } =>
|
332
|
-
"tags must be a tag_set of strings",
|
333
|
-
|
334
|
-
proc {|d| !d.has_key?(:regex_tags) ||
|
335
|
-
( d[:regex_tags].nil? ||
|
336
|
-
d[:regex_tags].is_a?(Set) &&
|
337
|
-
d[:regex_tags].all? {|et| et.is_a?(String)} ) } =>
|
338
|
-
"regex_tags must be a tag_set of strings",
|
339
|
-
|
340
|
-
# conversion to a schedule needs a time zone, any one will do
|
341
|
-
proc {|d| !d.has_key?(:time_restrictions) ||
|
342
|
-
( d[:time_restrictions].nil? ||
|
343
|
-
d[:time_restrictions].all? {|tr|
|
344
|
-
!!self.time_restriction_to_icecube_schedule(symbolize(tr), ActiveSupport::TimeZone['UTC'])
|
345
|
-
} )
|
346
|
-
} =>
|
347
|
-
"time restrictions are invalid",
|
348
|
-
|
349
|
-
# TODO should the media types be checked against a whitelist?
|
350
|
-
proc {|d| !d.has_key?(:unknown_media) ||
|
351
|
-
( d[:unknown_media].nil? ||
|
352
|
-
d[:unknown_media].is_a?(Array) &&
|
353
|
-
d[:unknown_media].all? {|et| et.is_a?(String)} ) } =>
|
354
|
-
"unknown_media must be a list of strings",
|
355
|
-
|
356
|
-
proc {|d| !d.has_key?(:warning_media) ||
|
357
|
-
( d[:warning_media].nil? ||
|
358
|
-
d[:warning_media].is_a?(Array) &&
|
359
|
-
d[:warning_media].all? {|et| et.is_a?(String)} ) } =>
|
360
|
-
"warning_media must be a list of strings",
|
361
|
-
|
362
|
-
proc {|d| !d.has_key?(:critical_media) ||
|
363
|
-
( d[:critical_media].nil? ||
|
364
|
-
d[:critical_media].is_a?(Array) &&
|
365
|
-
d[:critical_media].all? {|et| et.is_a?(String)} ) } =>
|
366
|
-
"critical_media must be a list of strings",
|
367
|
-
|
368
|
-
proc {|d| !d.has_key?(:unknown_blackhole) ||
|
369
|
-
[TrueClass, FalseClass].include?(d[:unknown_blackhole].class) } =>
|
370
|
-
"unknown_blackhole must be true or false",
|
371
|
-
|
372
|
-
proc {|d| !d.has_key?(:warning_blackhole) ||
|
373
|
-
[TrueClass, FalseClass].include?(d[:warning_blackhole].class) } =>
|
374
|
-
"warning_blackhole must be true or false",
|
375
|
-
|
376
|
-
proc {|d| !d.has_key?(:critical_blackhole) ||
|
377
|
-
[TrueClass, FalseClass].include?(d[:critical_blackhole].class) } =>
|
378
|
-
"critical_blackhole must be true or false",
|
379
|
-
}
|
380
|
-
|
381
|
-
def self.validate_data(d, options = {})
|
382
|
-
id_not_required = !!options[:id_not_required]
|
383
|
-
# hash with validation => error_message
|
384
|
-
validations = {}
|
385
|
-
validations.merge!({ proc { d.has_key?(:id) } => "id not set"}) unless id_not_required
|
386
|
-
validations.merge!(VALIDATION_PROCS)
|
387
|
-
|
388
|
-
errors = validations.keys.inject([]) {|ret,vk|
|
389
|
-
ret << "Rule #{validations[vk]}" unless vk.call(d)
|
390
|
-
ret
|
391
|
-
}
|
392
|
-
|
393
|
-
return if errors.empty?
|
394
|
-
|
395
|
-
if logger = options[:logger]
|
396
|
-
error_str = errors.join(", ")
|
397
|
-
logger.info "validation error: #{error_str}"
|
398
|
-
logger.debug "rule failing validations: #{d.inspect}"
|
399
|
-
end
|
400
|
-
errors
|
401
|
-
end
|
402
|
-
|
403
|
-
def refresh
|
404
|
-
rule_data = @redis.hgetall("notification_rule:#{@id}")
|
405
|
-
|
406
|
-
@contact_id = rule_data['contact_id']
|
407
|
-
tags = Flapjack.load_json(rule_data['tags'] || '')
|
408
|
-
@tags = tags ? Set.new(tags) : nil
|
409
|
-
regex_tags = Flapjack.load_json(rule_data['regex_tags'] || '')
|
410
|
-
@regex_tags = regex_tags ? Set.new(regex_tags) : nil
|
411
|
-
@entities = Flapjack.load_json(rule_data['entities'] || '')
|
412
|
-
@regex_entities = Flapjack.load_json(rule_data['regex_entities'] || '')
|
413
|
-
@time_restrictions = Flapjack.load_json(rule_data['time_restrictions'] || '')
|
414
|
-
@unknown_media = Flapjack.load_json(rule_data['unknown_media'] || '')
|
415
|
-
@warning_media = Flapjack.load_json(rule_data['warning_media'] || '')
|
416
|
-
@critical_media = Flapjack.load_json(rule_data['critical_media'] || '')
|
417
|
-
@unknown_blackhole = ((rule_data['unknown_blackhole'] || 'false').downcase == 'true')
|
418
|
-
@warning_blackhole = ((rule_data['warning_blackhole'] || 'false').downcase == 'true')
|
419
|
-
@critical_blackhole = ((rule_data['critical_blackhole'] || 'false').downcase == 'true')
|
420
|
-
end
|
421
|
-
|
422
|
-
end
|
423
|
-
end
|
424
|
-
end
|
425
|
-
|