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
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
module Flapjack
|
|
4
|
+
|
|
5
|
+
class RecordQueue
|
|
6
|
+
|
|
7
|
+
def initialize(queue, object_klass)
|
|
8
|
+
@queue = queue
|
|
9
|
+
@object_klass = object_klass
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def push(object)
|
|
13
|
+
Flapjack.redis.multi do
|
|
14
|
+
Flapjack.redis.lpush(@queue, object.id)
|
|
15
|
+
Flapjack.redis.lpush("#{@queue}_actions", "+")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def foreach(options = {})
|
|
20
|
+
while object_id = Flapjack.redis.rpop(@queue)
|
|
21
|
+
next unless object = @object_klass.find_by_id(object_id)
|
|
22
|
+
yield object if block_given?
|
|
23
|
+
object.destroy unless options[:keep]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def wait
|
|
28
|
+
Flapjack.redis.brpop("#{@queue}_actions")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
# defer initialisation for Redis connections until they're used.
|
|
4
|
+
require 'redis'
|
|
5
|
+
require 'redis/connection/hiredis'
|
|
6
|
+
require 'zermelo'
|
|
7
|
+
|
|
8
|
+
module Flapjack
|
|
9
|
+
|
|
10
|
+
class << self
|
|
11
|
+
# Thread and fiber-local
|
|
12
|
+
def redis
|
|
13
|
+
redis_cxn = Thread.current[:flapjack_redis]
|
|
14
|
+
return redis_cxn unless redis_cxn.nil?
|
|
15
|
+
Thread.current[:flapjack_redis] = Flapjack::RedisProxy.new
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class RedisProxy
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
attr_accessor :config
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def initialize
|
|
26
|
+
@proxied_connection = nil
|
|
27
|
+
@connection_failed = nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# need to override Kernel.exec
|
|
31
|
+
def exec
|
|
32
|
+
proxied_connection.exec
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def quit
|
|
36
|
+
@proxied_connection.quit unless @connection_failed || @proxied_connection.nil?
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def respond_to?(name, include_private = false)
|
|
40
|
+
proxied_connection.respond_to?(name, include_private)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def method_missing(name, *args, &block)
|
|
44
|
+
proxied_connection.send(name, *args, &block)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
REQUIRED_VERSION = '2.6.12'
|
|
50
|
+
|
|
51
|
+
def proxied_connection
|
|
52
|
+
return @proxied_connection unless @proxied_connection.nil?
|
|
53
|
+
@proxied_connection = ::Redis.new(self.class.config)
|
|
54
|
+
redis_version = @proxied_connection.info['redis_version']
|
|
55
|
+
return @proxied_connection if redis_version.nil? ||
|
|
56
|
+
((redis_version.split('.') <=> REQUIRED_VERSION.split('.')) >= 0)
|
|
57
|
+
raise("Redis too old - Flapjack requires #{REQUIRED_VERSION} but " \
|
|
58
|
+
"#{redis_version} is running")
|
|
59
|
+
rescue Redis::CannotConnectError, Errno::EINVAL
|
|
60
|
+
@connection_failed = true
|
|
61
|
+
raise
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
data/lib/flapjack/utility.rb
CHANGED
|
@@ -15,21 +15,21 @@ module Flapjack
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
# Returns relative time in words referencing the given date
|
|
18
|
-
# relative_time_ago(Time.now) => 'about a minute ago'
|
|
19
|
-
def relative_time_ago(from_time)
|
|
20
|
-
distance_in_minutes = (((
|
|
18
|
+
# relative_time_ago(Time.now, Time.now - 1) => 'about a minute ago'
|
|
19
|
+
def relative_time_ago(from_time, to_time)
|
|
20
|
+
distance_in_minutes = (((from_time.to_time - to_time.to_time).abs)/60).round
|
|
21
21
|
case distance_in_minutes
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
22
|
+
when 0..1 then 'about a minute'
|
|
23
|
+
when 2..44 then "#{distance_in_minutes} minutes"
|
|
24
|
+
when 45..89 then 'about 1 hour'
|
|
25
|
+
when 90..1439 then "about #{(distance_in_minutes.to_f / 60.0).round} hours"
|
|
26
|
+
when 1440..2439 then '1 day'
|
|
27
|
+
when 2440..2879 then 'about 2 days'
|
|
28
|
+
when 2880..43199 then "#{(distance_in_minutes / 1440).round} days"
|
|
29
|
+
when 43200..86399 then 'about 1 month'
|
|
30
|
+
when 86400..525599 then "#{(distance_in_minutes / 43200).round} months"
|
|
31
|
+
when 525600..1051199 then 'about 1 year'
|
|
32
|
+
else "over #{(distance_in_minutes / 525600).round} years"
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -47,10 +47,16 @@ module Flapjack
|
|
|
47
47
|
Time.utc(time.year, time.month, time.day, time.hour, time.min, time.sec)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
def stringify(obj)
|
|
51
|
+
return obj.inject({}){|memo,(k,v)| memo[k.to_s] = stringify(v); memo} if obj.is_a?(Hash)
|
|
52
|
+
return obj.inject([]){|memo,v | memo << stringify(v); memo} if obj.is_a?(Array)
|
|
53
|
+
obj
|
|
54
|
+
end
|
|
55
|
+
|
|
50
56
|
def symbolize(obj)
|
|
51
57
|
return obj.inject({}){|memo,(k,v)| memo[k.to_sym] = symbolize(v); memo} if obj.is_a? Hash
|
|
52
58
|
return obj.inject([]){|memo,v | memo << symbolize(v); memo} if obj.is_a? Array
|
|
53
|
-
|
|
59
|
+
obj
|
|
54
60
|
end
|
|
55
61
|
|
|
56
62
|
# The passed block will be provided each value from the args
|
data/lib/flapjack/version.rb
CHANGED
data/libexec/httpbroker.go
CHANGED
|
@@ -5,26 +5,130 @@ import (
|
|
|
5
5
|
"flapjack"
|
|
6
6
|
"fmt"
|
|
7
7
|
"github.com/go-martini/martini"
|
|
8
|
-
"gopkg.in/alecthomas/kingpin.
|
|
8
|
+
"gopkg.in/alecthomas/kingpin.v2"
|
|
9
9
|
"io/ioutil"
|
|
10
10
|
"log"
|
|
11
11
|
"net/http"
|
|
12
12
|
"os"
|
|
13
|
+
"strings"
|
|
13
14
|
"time"
|
|
14
15
|
)
|
|
15
16
|
|
|
17
|
+
type EventFormat int
|
|
18
|
+
|
|
19
|
+
const (
|
|
20
|
+
Normal EventFormat = 1
|
|
21
|
+
SNS EventFormat = 2
|
|
22
|
+
Newrelic EventFormat = 3
|
|
23
|
+
)
|
|
24
|
+
|
|
16
25
|
// State is a basic representation of a Flapjack event, with some extra field.
|
|
17
26
|
// The extra fields handle state expiry.
|
|
18
27
|
// Find more at http://flapjack.io/docs/1.0/development/DATA_STRUCTURES
|
|
28
|
+
type Tags struct {
|
|
29
|
+
FromBroker string `json:"from_broker"`
|
|
30
|
+
}
|
|
19
31
|
type State struct {
|
|
32
|
+
flapjack.Event
|
|
33
|
+
TTL int64 `json:"ttl"`
|
|
34
|
+
Tags struct {
|
|
35
|
+
FromBroker string `json:"from_broker"`
|
|
36
|
+
} `json:"tags"`
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
type InputState struct {
|
|
20
40
|
flapjack.Event
|
|
21
41
|
TTL int64 `json:"ttl"`
|
|
22
42
|
}
|
|
23
43
|
|
|
44
|
+
type SNSSubscribe struct {
|
|
45
|
+
Message string `json:"Message"`
|
|
46
|
+
MessageID string `json:"MessageId"`
|
|
47
|
+
Signature string `json:"Signature"`
|
|
48
|
+
SignatureVersion string `json:"SignatureVersion"`
|
|
49
|
+
SigningCertURL string `json:"SigningCertURL"`
|
|
50
|
+
SubscribeURL string `json:"SubscribeURL"`
|
|
51
|
+
Timestamp string `json:"Timestamp"`
|
|
52
|
+
Token string `json:"Token"`
|
|
53
|
+
TopicArn string `json:"TopicArn"`
|
|
54
|
+
Type string `json:"Type"`
|
|
55
|
+
}
|
|
56
|
+
type SNSNotification struct {
|
|
57
|
+
Message string `json:"Message"`
|
|
58
|
+
MessageID string `json:"MessageId"`
|
|
59
|
+
Signature string `json:"Signature"`
|
|
60
|
+
SignatureVersion string `json:"SignatureVersion"`
|
|
61
|
+
SigningCertURL string `json:"SigningCertURL"`
|
|
62
|
+
Subject string `json:"Subject"`
|
|
63
|
+
Timestamp string `json:"Timestamp"`
|
|
64
|
+
TopicArn string `json:"TopicArn"`
|
|
65
|
+
Type string `json:"Type"`
|
|
66
|
+
UnsubscribeURL string `json:"UnsubscribeURL"`
|
|
67
|
+
}
|
|
68
|
+
type CWAlarm struct {
|
|
69
|
+
AWSAccountID string `json:"AWSAccountId"`
|
|
70
|
+
AlarmDescription interface{} `json:"AlarmDescription"`
|
|
71
|
+
AlarmName string `json:"AlarmName"`
|
|
72
|
+
NewStateReason string `json:"NewStateReason"`
|
|
73
|
+
NewStateValue string `json:"NewStateValue"`
|
|
74
|
+
OldStateValue string `json:"OldStateValue"`
|
|
75
|
+
Region string `json:"Region"`
|
|
76
|
+
StateChangeTime string `json:"StateChangeTime"`
|
|
77
|
+
Time int64 `json:"Time"`
|
|
78
|
+
Trigger struct {
|
|
79
|
+
ComparisonOperator string `json:"ComparisonOperator"`
|
|
80
|
+
Dimensions []struct {
|
|
81
|
+
Name string `json:"name"`
|
|
82
|
+
Value string `json:"value"`
|
|
83
|
+
} `json:"Dimensions"`
|
|
84
|
+
EvaluationPeriods int `json:"EvaluationPeriods"`
|
|
85
|
+
MetricName string `json:"MetricName"`
|
|
86
|
+
Namespace string `json:"Namespace"`
|
|
87
|
+
Period int `json:"Period"`
|
|
88
|
+
Statistic string `json:"Statistic"`
|
|
89
|
+
Threshold float64 `json:"Threshold"`
|
|
90
|
+
Unit interface{} `json:"Unit"`
|
|
91
|
+
} `json:"Trigger"`
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
type NewRelicAlert struct {
|
|
95
|
+
AccountID int `json:"account_id"`
|
|
96
|
+
AccountName string `json:"account_name"`
|
|
97
|
+
ConditionID int `json:"condition_id"`
|
|
98
|
+
ConditionName string `json:"condition_name"`
|
|
99
|
+
CurrentState string `json:"current_state"`
|
|
100
|
+
Details string `json:"details"`
|
|
101
|
+
EventType string `json:"event_type"`
|
|
102
|
+
IncidentAcknowledgeURL string `json:"incident_acknowledge_url"`
|
|
103
|
+
IncidentID int `json:"incident_id"`
|
|
104
|
+
IncidentURL string `json:"incident_url"`
|
|
105
|
+
Owner string `json:"owner"`
|
|
106
|
+
PolicyName string `json:"policy_name"`
|
|
107
|
+
PolicyURL string `json:"policy_url"`
|
|
108
|
+
RunbookURL string `json:"runbook_url"`
|
|
109
|
+
Severity string `json:"severity"`
|
|
110
|
+
Targets []struct {
|
|
111
|
+
ID string `json:"id"`
|
|
112
|
+
Labels struct {
|
|
113
|
+
Label string `json:"label"`
|
|
114
|
+
} `json:"labels"`
|
|
115
|
+
Link string `json:"link"`
|
|
116
|
+
Name string `json:"name"`
|
|
117
|
+
Product string `json:"product"`
|
|
118
|
+
Type string `json:"type"`
|
|
119
|
+
} `json:"targets"`
|
|
120
|
+
Timestamp int `json:"timestamp"`
|
|
121
|
+
}
|
|
122
|
+
|
|
24
123
|
// handler caches
|
|
25
124
|
func CreateState(updates chan State, w http.ResponseWriter, r *http.Request) {
|
|
26
125
|
var state State
|
|
27
|
-
|
|
126
|
+
var input_state InputState
|
|
127
|
+
var event_format EventFormat
|
|
128
|
+
var NRAlarm NewRelicAlert
|
|
129
|
+
var SNSData SNSNotification
|
|
130
|
+
var tags Tags
|
|
131
|
+
tags.FromBroker = "httpbroker"
|
|
28
132
|
body, err := ioutil.ReadAll(r.Body)
|
|
29
133
|
if err != nil {
|
|
30
134
|
message := "Error: Couldn't read request body: %s\n"
|
|
@@ -33,12 +137,105 @@ func CreateState(updates chan State, w http.ResponseWriter, r *http.Request) {
|
|
|
33
137
|
return
|
|
34
138
|
}
|
|
35
139
|
|
|
140
|
+
// Check if its a FJ event
|
|
36
141
|
err = json.Unmarshal(body, &state)
|
|
37
|
-
if
|
|
38
|
-
message := "
|
|
39
|
-
log.
|
|
40
|
-
|
|
41
|
-
|
|
142
|
+
if state.Event.Entity != "" {
|
|
143
|
+
message := "Got Flapjack event"
|
|
144
|
+
log.Printf(message)
|
|
145
|
+
event_format = Normal
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Check if its a New Relic event
|
|
149
|
+
err = json.Unmarshal(body, &NRAlarm)
|
|
150
|
+
if NRAlarm.ConditionName != "" {
|
|
151
|
+
message := "Got New Relic event"
|
|
152
|
+
log.Printf(message)
|
|
153
|
+
event_format = Newrelic
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Check if its a SNS
|
|
157
|
+
err = json.Unmarshal(body, &SNSData)
|
|
158
|
+
if SNSData.SigningCertURL != "" {
|
|
159
|
+
message := "Got SNS event"
|
|
160
|
+
log.Printf(message)
|
|
161
|
+
event_format = SNS
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
switch event_format {
|
|
165
|
+
case Normal:
|
|
166
|
+
err = json.Unmarshal(body, &input_state)
|
|
167
|
+
if err != nil {
|
|
168
|
+
message := "Error: Couldn't read request body: %s\n"
|
|
169
|
+
log.Println(message, err)
|
|
170
|
+
fmt.Fprintf(w, message, err)
|
|
171
|
+
return
|
|
172
|
+
}
|
|
173
|
+
case Newrelic:
|
|
174
|
+
var event_state string
|
|
175
|
+
switch strings.ToLower(NRAlarm.CurrentState) {
|
|
176
|
+
case "alarm":
|
|
177
|
+
event_state = "critical"
|
|
178
|
+
default:
|
|
179
|
+
event_state = "ok"
|
|
180
|
+
}
|
|
181
|
+
new_details := fmt.Sprint("New Relic Alert Received: ", NRAlarm.Details, " Ack the alert using the following URL: ", NRAlarm.IncidentAcknowledgeURL)
|
|
182
|
+
state = State{
|
|
183
|
+
flapjack.Event{
|
|
184
|
+
Entity: NRAlarm.PolicyName,
|
|
185
|
+
Check: NRAlarm.ConditionName,
|
|
186
|
+
// Type: "service", // @TODO: Make this magic
|
|
187
|
+
State: event_state,
|
|
188
|
+
Summary: new_details,
|
|
189
|
+
},
|
|
190
|
+
0,
|
|
191
|
+
tags,
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
case SNS:
|
|
195
|
+
var sns_subscription SNSSubscribe
|
|
196
|
+
var cw_alarm CWAlarm
|
|
197
|
+
|
|
198
|
+
body, err := ioutil.ReadAll(r.Body)
|
|
199
|
+
if err != nil {
|
|
200
|
+
message := "Error: Couldn't read request body: %s\n"
|
|
201
|
+
log.Printf(message, err)
|
|
202
|
+
fmt.Fprintf(w, message, err)
|
|
203
|
+
return
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
json.Unmarshal(body, &sns_subscription)
|
|
207
|
+
if sns_subscription.SubscribeURL != "" {
|
|
208
|
+
http.Get(sns_subscription.SubscribeURL)
|
|
209
|
+
return
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
input_message := []byte(SNSData.Message)
|
|
213
|
+
err = json.Unmarshal(input_message, &cw_alarm)
|
|
214
|
+
if err != nil {
|
|
215
|
+
message := "Error: Couldn't read request body from the SNS message: %s\n"
|
|
216
|
+
log.Println(message, err)
|
|
217
|
+
fmt.Fprintf(w, message, err)
|
|
218
|
+
return
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
var event_state string
|
|
222
|
+
switch strings.ToLower(cw_alarm.NewStateValue) {
|
|
223
|
+
case "alarm":
|
|
224
|
+
event_state = "critical"
|
|
225
|
+
default:
|
|
226
|
+
event_state = "ok"
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
state = State{
|
|
230
|
+
flapjack.Event{
|
|
231
|
+
Entity: cw_alarm.AlarmName,
|
|
232
|
+
Check: cw_alarm.Trigger.MetricName,
|
|
233
|
+
State: event_state,
|
|
234
|
+
Summary: cw_alarm.NewStateReason,
|
|
235
|
+
},
|
|
236
|
+
0,
|
|
237
|
+
tags,
|
|
238
|
+
}
|
|
42
239
|
}
|
|
43
240
|
|
|
44
241
|
// Populate a time if none has been set.
|
|
@@ -54,6 +251,10 @@ func CreateState(updates chan State, w http.ResponseWriter, r *http.Request) {
|
|
|
54
251
|
state.TTL = 300
|
|
55
252
|
}
|
|
56
253
|
|
|
254
|
+
if state.Tags.FromBroker == "" {
|
|
255
|
+
state.Tags.FromBroker = "httpbroker"
|
|
256
|
+
}
|
|
257
|
+
|
|
57
258
|
updates <- state
|
|
58
259
|
|
|
59
260
|
json, _ := json.Marshal(state)
|
|
@@ -110,11 +311,12 @@ func submitCachedState(states map[string]State, config Config) {
|
|
|
110
311
|
}
|
|
111
312
|
|
|
112
313
|
var (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
314
|
+
app = kingpin.New("httpbroker", "Accepts HTTP events for Flapjack.")
|
|
315
|
+
port = app.Flag("port", "Address to bind HTTP server (default 3090)").Default("3090").OverrideDefaultFromEnvar("PORT").String()
|
|
316
|
+
server = app.Flag("server", "Redis server to connect to (default localhost:6380)").Default("localhost:6380").String()
|
|
317
|
+
database = app.Flag("database", "Redis database to connect to (default 0)").Int() // .Default("13").Int()
|
|
318
|
+
interval = app.Flag("interval", "How often to submit events (default 10s)").Default("10s").Duration()
|
|
319
|
+
debug = app.Flag("debug", "Enable verbose output (default false)").Bool()
|
|
118
320
|
)
|
|
119
321
|
|
|
120
322
|
type Config struct {
|
|
@@ -126,8 +328,10 @@ type Config struct {
|
|
|
126
328
|
}
|
|
127
329
|
|
|
128
330
|
func main() {
|
|
129
|
-
|
|
130
|
-
|
|
331
|
+
app.Version("0.0.1")
|
|
332
|
+
app.Writer(os.Stdout) // direct help to stdout
|
|
333
|
+
kingpin.MustParse(app.Parse(os.Args[1:]))
|
|
334
|
+
app.Writer(os.Stderr) // ... but ensure errors go to stderr
|
|
131
335
|
|
|
132
336
|
config := Config{
|
|
133
337
|
Server: *server,
|
data/libexec/oneoff.go
CHANGED
|
@@ -4,25 +4,28 @@ import (
|
|
|
4
4
|
"encoding/json"
|
|
5
5
|
"flapjack"
|
|
6
6
|
"fmt"
|
|
7
|
-
"gopkg.in/alecthomas/kingpin.
|
|
7
|
+
"gopkg.in/alecthomas/kingpin.v2"
|
|
8
8
|
"os"
|
|
9
9
|
"strings"
|
|
10
10
|
"time"
|
|
11
11
|
)
|
|
12
12
|
|
|
13
13
|
var (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
app = kingpin.New("oneoff", "Submits a single event to Flapjack.")
|
|
15
|
+
entity = app.Arg("entity", "Entity name").Required().String()
|
|
16
|
+
check = app.Arg("check", "Check name").Required().String()
|
|
17
|
+
state = app.Arg("state", "Current state").Required().String()
|
|
18
|
+
summary = app.Arg("summary", "Summary of event").Required().String()
|
|
19
|
+
debug = app.Flag("debug", "Enable verbose output (default false)").Bool()
|
|
20
|
+
server = app.Flag("server", "Redis server to connect to (default localhost:6380)").Default("localhost:6380").String()
|
|
21
|
+
database = app.Flag("database", "Redis database to connect to (default 0)").Int()
|
|
21
22
|
)
|
|
22
23
|
|
|
23
24
|
func main() {
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
app.Version("0.0.1")
|
|
26
|
+
app.Writer(os.Stdout) // direct help to stdout
|
|
27
|
+
kingpin.MustParse(app.Parse(os.Args[1:]))
|
|
28
|
+
app.Writer(os.Stderr) // ... but ensure errors go to stderr
|
|
26
29
|
|
|
27
30
|
if *debug {
|
|
28
31
|
fmt.Println("Entity:", *entity)
|