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
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
<% check = @alert.check -%>
|
|
2
|
+
<% type = @alert.type -%>
|
|
1
3
|
<%= @alert.type_sentence_case -%>
|
|
2
|
-
: <%
|
|
3
|
-
|
|
4
|
-
<% unless ['acknowledgement', 'test'].include?(
|
|
4
|
+
: <% unless @ack_str.nil? || @ack_str.empty? %><%= @ack_str %>, <% end -%>
|
|
5
|
+
<%= '"' + check.name + '"' -%>
|
|
6
|
+
<% unless ['acknowledgement', 'test'].include?(type) -%>
|
|
5
7
|
is <%= @alert.state_title_case -%>
|
|
6
8
|
<% end -%>
|
|
7
|
-
<% if
|
|
9
|
+
<% if 'acknowledgement'.eql?(type) -%>
|
|
8
10
|
has been acknowledged, unscheduled maintenance created for <%= time_period_in_words(@alert.acknowledgement_duration) -%>
|
|
9
11
|
<% end -%>
|
|
10
|
-
<%
|
|
11
|
-
|
|
12
|
+
<% summary = @alert.summary -%>
|
|
13
|
+
<% unless summary.nil? || summary.empty? -%>
|
|
14
|
+
, <%= summary -%>
|
|
12
15
|
<% end -%>
|
|
@@ -3,27 +3,40 @@
|
|
|
3
3
|
# A HTTP-based API server, which provides queries to determine the status of
|
|
4
4
|
# entities and the checks that are reported against them.
|
|
5
5
|
#
|
|
6
|
-
# There's a matching flapjack-diner gem at https://github.com/
|
|
6
|
+
# There's a matching flapjack-diner gem at https://github.com/flpjck/flapjack-diner
|
|
7
7
|
# which consumes data from this API.
|
|
8
8
|
|
|
9
9
|
require 'time'
|
|
10
10
|
|
|
11
|
-
require 'rack/fiber_pool'
|
|
12
11
|
require 'sinatra/base'
|
|
13
12
|
|
|
14
|
-
require '
|
|
15
|
-
require 'flapjack/redis_pool'
|
|
13
|
+
require 'active_support/inflector'
|
|
16
14
|
|
|
17
|
-
require '
|
|
15
|
+
require 'swagger/blocks'
|
|
18
16
|
|
|
19
|
-
require 'flapjack
|
|
20
|
-
require 'flapjack/
|
|
21
|
-
|
|
22
|
-
require 'flapjack/
|
|
23
|
-
require 'flapjack/
|
|
24
|
-
require 'flapjack/
|
|
25
|
-
require 'flapjack/
|
|
26
|
-
require 'flapjack/
|
|
17
|
+
require 'flapjack'
|
|
18
|
+
require 'flapjack/utility'
|
|
19
|
+
|
|
20
|
+
require 'flapjack/data/acknowledgement'
|
|
21
|
+
require 'flapjack/data/check'
|
|
22
|
+
require 'flapjack/data/contact'
|
|
23
|
+
require 'flapjack/data/medium'
|
|
24
|
+
require 'flapjack/data/metrics'
|
|
25
|
+
require 'flapjack/data/rule'
|
|
26
|
+
require 'flapjack/data/scheduled_maintenance'
|
|
27
|
+
require 'flapjack/data/statistic'
|
|
28
|
+
require 'flapjack/data/state'
|
|
29
|
+
require 'flapjack/data/tag'
|
|
30
|
+
require 'flapjack/data/test_notification'
|
|
31
|
+
require 'flapjack/data/unscheduled_maintenance'
|
|
32
|
+
|
|
33
|
+
require 'flapjack/gateways/jsonapi/middleware/array_param_fixer'
|
|
34
|
+
require 'flapjack/gateways/jsonapi/middleware/json_params_parser'
|
|
35
|
+
require 'flapjack/gateways/jsonapi/middleware/request_timestamp'
|
|
36
|
+
|
|
37
|
+
%w[headers miscellaneous resources serialiser swagger_docs].each do |helper|
|
|
38
|
+
require "flapjack/gateways/jsonapi/helpers/#{helper}"
|
|
39
|
+
end
|
|
27
40
|
|
|
28
41
|
module Flapjack
|
|
29
42
|
|
|
@@ -33,207 +46,104 @@ module Flapjack
|
|
|
33
46
|
|
|
34
47
|
include Flapjack::Utility
|
|
35
48
|
|
|
36
|
-
|
|
37
|
-
#
|
|
38
|
-
JSONAPI_MEDIA_TYPE = 'application/vnd.api+json'
|
|
39
|
-
# http://tools.ietf.org/html/rfc6902
|
|
40
|
-
JSON_PATCH_MEDIA_TYPE = 'application/json-patch+json'
|
|
41
|
-
|
|
42
|
-
class ContactNotFound < RuntimeError
|
|
43
|
-
attr_reader :contact_id
|
|
44
|
-
def initialize(contact_id)
|
|
45
|
-
@contact_id = contact_id
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
class ContactsNotFound < RuntimeError
|
|
50
|
-
attr_reader :contact_ids
|
|
51
|
-
def initialize(contact_ids)
|
|
52
|
-
@contact_ids = contact_ids
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
class NotificationRuleNotFound < RuntimeError
|
|
57
|
-
attr_reader :notification_rule_id
|
|
58
|
-
def initialize(notification_rule_id)
|
|
59
|
-
@notification_rule_id = notification_rule_id
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
class NotificationRulesNotFound < RuntimeError
|
|
64
|
-
attr_reader :notification_rule_ids
|
|
65
|
-
def initialize(notification_rule_ids)
|
|
66
|
-
@notification_rule_ids = notification_rule_ids
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
class EntityNotFound < RuntimeError
|
|
71
|
-
attr_reader :entity
|
|
72
|
-
def initialize(entity)
|
|
73
|
-
@entity = entity
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
class EntitiesNotFound < RuntimeError
|
|
78
|
-
attr_reader :entity_ids
|
|
79
|
-
def initialize(entity_ids)
|
|
80
|
-
@entity_ids = entity_ids
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
class EntityCheckNotFound < RuntimeError
|
|
85
|
-
attr_reader :entity, :check
|
|
86
|
-
def initialize(entity, check)
|
|
87
|
-
@entity = entity
|
|
88
|
-
@check = check
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
class EntityChecksNotFound < RuntimeError
|
|
93
|
-
attr_reader :entity_checks
|
|
94
|
-
def initialize(entity_checks)
|
|
95
|
-
@entity_checks = entity_checks
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
class ResourceLocked < RuntimeError
|
|
100
|
-
attr_reader :resource
|
|
101
|
-
def initialize(resource)
|
|
102
|
-
@resource = resource
|
|
103
|
-
end
|
|
104
|
-
end
|
|
49
|
+
# TODO clean up media type handling for variable character sets
|
|
50
|
+
# append charset in use
|
|
105
51
|
|
|
106
|
-
|
|
52
|
+
# http://jsonapi.org/extensions/bulk/
|
|
53
|
+
# http://www.iana.org/assignments/media-types/application/vnd.api+json
|
|
54
|
+
JSONAPI_MEDIA_TYPE = 'application/vnd.api+json'
|
|
55
|
+
JSONAPI_MEDIA_TYPE_BULK = 'application/vnd.api+json; ext=bulk'
|
|
56
|
+
|
|
57
|
+
# # http://tools.ietf.org/html/rfc6902
|
|
58
|
+
# JSON_PATCH_MEDIA_TYPE = 'application/json-patch+json; charset=utf-8'
|
|
59
|
+
|
|
60
|
+
RESOURCE_CLASSES = [
|
|
61
|
+
Flapjack::Data::Acknowledgement,
|
|
62
|
+
Flapjack::Data::Check,
|
|
63
|
+
Flapjack::Data::Contact,
|
|
64
|
+
Flapjack::Data::Medium,
|
|
65
|
+
Flapjack::Data::Rule,
|
|
66
|
+
Flapjack::Data::ScheduledMaintenance,
|
|
67
|
+
Flapjack::Data::State,
|
|
68
|
+
Flapjack::Data::Statistic,
|
|
69
|
+
Flapjack::Data::Tag,
|
|
70
|
+
Flapjack::Data::TestNotification,
|
|
71
|
+
Flapjack::Data::UnscheduledMaintenance
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
set :root, File.dirname(__FILE__)
|
|
75
|
+
|
|
76
|
+
set :raise_errors, false
|
|
77
|
+
set :show_exceptions, false
|
|
107
78
|
|
|
108
79
|
set :protection, :except => :path_traversal
|
|
109
80
|
|
|
110
|
-
|
|
81
|
+
use Flapjack::Gateways::JSONAPI::Middleware::RequestTimestamp
|
|
82
|
+
use ::Rack::MethodOverride
|
|
83
|
+
use Flapjack::Gateways::JSONAPI::Middleware::ArrayParamFixer
|
|
84
|
+
use Flapjack::Gateways::JSONAPI::Middleware::JsonParamsParser
|
|
111
85
|
|
|
112
|
-
|
|
113
|
-
if !msg || msg.empty?
|
|
114
|
-
trace = exception.backtrace.join("\n")
|
|
115
|
-
msg = "#{exception.class} - #{exception.message}"
|
|
116
|
-
msg_str = "#{msg}\n#{trace}"
|
|
117
|
-
else
|
|
118
|
-
msg_str = msg.join(", ")
|
|
119
|
-
end
|
|
120
|
-
case
|
|
121
|
-
when status < 500
|
|
122
|
-
@logger.warn "Error: #{msg_str}"
|
|
123
|
-
else
|
|
124
|
-
@logger.error "Error: #{msg_str}"
|
|
125
|
-
end
|
|
86
|
+
class << self
|
|
126
87
|
|
|
127
|
-
|
|
88
|
+
@@lock = Monitor.new
|
|
128
89
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if @logger.debug?
|
|
132
|
-
@logger.debug("Returning #{status} for #{request_info[:request_method]} " +
|
|
133
|
-
"#{request_info[:path_info]}#{query_string}, body: #{response_body}")
|
|
134
|
-
elsif @logger.info?
|
|
135
|
-
@logger.info("Returning #{status} for #{request_info[:request_method]} " +
|
|
136
|
-
"#{request_info[:path_info]}#{query_string}")
|
|
137
|
-
end
|
|
90
|
+
def start
|
|
91
|
+
Flapjack.logger.info "starting jsonapi - class"
|
|
138
92
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
93
|
+
if access_log = (@config && @config['access_log'])
|
|
94
|
+
unless File.directory?(File.dirname(access_log))
|
|
95
|
+
raise "Parent directory for log file #{access_log} doesn't exist"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
@access_log = ::Logger.new(@config['access_log'])
|
|
99
|
+
use Rack::CommonLogger, @access_log
|
|
144
100
|
end
|
|
145
101
|
|
|
146
|
-
[status, headers, response_body]
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
request_info = {
|
|
150
|
-
:path_info => env['REQUEST_PATH'],
|
|
151
|
-
:request_method => env['REQUEST_METHOD'],
|
|
152
|
-
:query_string => env['QUERY_STRING']
|
|
153
|
-
}
|
|
154
|
-
case e
|
|
155
|
-
when Flapjack::Gateways::JSONAPI::ContactNotFound
|
|
156
|
-
rescue_error.call(404, e, request_info, "could not find contact '#{e.contact_id}'")
|
|
157
|
-
when Flapjack::Gateways::JSONAPI::ContactsNotFound
|
|
158
|
-
rescue_error.call(404, e, request_info, "could not find contacts '" + e.contact_ids.join(', ') + "'")
|
|
159
|
-
when Flapjack::Gateways::JSONAPI::NotificationRuleNotFound
|
|
160
|
-
rescue_error.call(404, e, request_info,"could not find notification rule '#{e.notification_rule_id}'")
|
|
161
|
-
when Flapjack::Gateways::JSONAPI::NotificationRulesNotFound
|
|
162
|
-
rescue_error.call(404, e, request_info, "could not find notification rules '" + e.notification_rule_ids.join(', ') + "'")
|
|
163
|
-
when Flapjack::Gateways::JSONAPI::EntityNotFound
|
|
164
|
-
rescue_error.call(404, e, request_info, "could not find entity '#{e.entity}'")
|
|
165
|
-
when Flapjack::Gateways::JSONAPI::EntitiesNotFound
|
|
166
|
-
entity_ids = "'" + e.entity_ids.join("', '") + "'"
|
|
167
|
-
rescue_error.call(404, e, request_info, "could not find entities: #{entity_ids}")
|
|
168
|
-
when Flapjack::Gateways::JSONAPI::EntityCheckNotFound
|
|
169
|
-
rescue_error.call(404, e, request_info, "could not find entity check '#{e.check}'")
|
|
170
|
-
when Flapjack::Gateways::JSONAPI::EntityChecksNotFound
|
|
171
|
-
checks = "'" + e.entity_checks.join("', '") + "'"
|
|
172
|
-
rescue_error.call(404, e, request_info, "could not find entity checks: #{checks}")
|
|
173
|
-
when Flapjack::Gateways::JSONAPI::ResourceLocked
|
|
174
|
-
rescue_error.call(423, e, request_info, "unable to obtain lock for resource '#{e.resource}'")
|
|
175
|
-
else
|
|
176
|
-
rescue_error.call(500, e, request_info)
|
|
177
102
|
end
|
|
178
|
-
}
|
|
179
|
-
use ::Rack::FiberPool, :size => 25, :rescue_exception => @rescue_exception
|
|
180
103
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
class << self
|
|
185
|
-
def start
|
|
186
|
-
@redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2, :logger => @logger)
|
|
187
|
-
|
|
188
|
-
@logger.info "starting jsonapi - class"
|
|
189
|
-
|
|
190
|
-
if @config && @config['access_log']
|
|
191
|
-
access_logger = Flapjack::AsyncLogger.new(@config['access_log'])
|
|
192
|
-
use Flapjack::CommonLogger, access_logger
|
|
104
|
+
def media_type_produced(options = {})
|
|
105
|
+
unless options[:with_charset].is_a?(TrueClass)
|
|
106
|
+
return 'application/vnd.api+json; supported-ext=bulk'
|
|
193
107
|
end
|
|
194
108
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
end
|
|
204
|
-
if (@base_url =~ /^#{URI::regexp(%w(http https))}$/).nil?
|
|
205
|
-
@logger.error "base_url must be a valid http or https URI (#{@base_url}), setting to dummy value (#{dummy_url})"
|
|
206
|
-
# FIXME: at this point I'd like to stop this pikelet without bringing down the whole
|
|
207
|
-
# flapjack process
|
|
208
|
-
# For now, set a dummy value
|
|
209
|
-
@base_url = dummy_url
|
|
109
|
+
media_type = nil
|
|
110
|
+
@@lock.synchronize do
|
|
111
|
+
encoding = Encoding.default_external
|
|
112
|
+
media_type = if encoding.nil?
|
|
113
|
+
'application/vnd.api+json; supported-ext=bulk'
|
|
114
|
+
else
|
|
115
|
+
"application/vnd.api+json; supported-ext=bulk; charset=#{encoding.name.downcase}"
|
|
116
|
+
end
|
|
210
117
|
end
|
|
118
|
+
media_type
|
|
211
119
|
end
|
|
212
120
|
end
|
|
213
121
|
|
|
214
|
-
def
|
|
215
|
-
self.class.instance_variable_get(
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
def logger
|
|
219
|
-
self.class.instance_variable_get('@logger')
|
|
122
|
+
def config
|
|
123
|
+
self.class.instance_variable_get("@config")
|
|
220
124
|
end
|
|
221
125
|
|
|
222
|
-
def
|
|
223
|
-
self.class.
|
|
126
|
+
def media_type_produced(options = {})
|
|
127
|
+
self.class.media_type_produced(options)
|
|
224
128
|
end
|
|
225
129
|
|
|
226
130
|
before do
|
|
131
|
+
# needs to be done per-thread...
|
|
132
|
+
Flapjack.configure_log('jsonapi', config['logger'])
|
|
133
|
+
|
|
134
|
+
# ... as does this
|
|
135
|
+
Zermelo.redis ||= Flapjack.redis
|
|
136
|
+
|
|
227
137
|
input = nil
|
|
228
138
|
query_string = (request.query_string.respond_to?(:length) &&
|
|
229
|
-
|
|
230
|
-
if logger.debug?
|
|
139
|
+
request.query_string.length > 0) ? "?#{request.query_string}" : ""
|
|
140
|
+
if Flapjack.logger.debug?
|
|
231
141
|
input = env['rack.input'].read
|
|
232
|
-
logger.debug("#{request.request_method} #{request.path_info}#{query_string} Headers: #{headers.inspect}, Body: #{input}")
|
|
233
|
-
elsif logger.info?
|
|
142
|
+
Flapjack.logger.debug("#{request.request_method} #{request.path_info}#{query_string} Headers: #{headers.inspect}, Body: #{input}")
|
|
143
|
+
elsif Flapjack.logger.info?
|
|
234
144
|
input = env['rack.input'].read
|
|
235
145
|
input_short = input.gsub(/\n/, '').gsub(/\s+/, ' ')
|
|
236
|
-
logger.info("#{request.request_method} #{request.path_info}#{query_string} #{input_short[0..80]}")
|
|
146
|
+
Flapjack.logger.info("#{request.request_method} #{request.path_info}#{query_string} #{input_short[0..80]}")
|
|
237
147
|
end
|
|
238
148
|
env['rack.input'].rewind unless input.nil?
|
|
239
149
|
end
|
|
@@ -243,7 +153,7 @@ module Flapjack
|
|
|
243
153
|
|
|
244
154
|
query_string = (request.query_string.respond_to?(:length) &&
|
|
245
155
|
request.query_string.length > 0) ? "?#{request.query_string}" : ""
|
|
246
|
-
if logger.debug?
|
|
156
|
+
if Flapjack.logger.debug?
|
|
247
157
|
body_debug = case
|
|
248
158
|
when response.body.respond_to?(:each)
|
|
249
159
|
response.body.each_with_index {|r, i| "body[#{i}]: #{r}"}.join(', ')
|
|
@@ -251,181 +161,41 @@ module Flapjack
|
|
|
251
161
|
response.body.to_s
|
|
252
162
|
end
|
|
253
163
|
headers_debug = response.headers.to_s
|
|
254
|
-
logger.debug("Returning #{response.status} for #{request.request_method} " +
|
|
164
|
+
Flapjack.logger.debug("Returning #{response.status} for #{request.request_method} " +
|
|
255
165
|
"#{request.path_info}#{query_string}, headers: #{headers_debug}, body: #{body_debug}")
|
|
256
|
-
elsif logger.info?
|
|
257
|
-
logger.info("Returning #{response.status} for #{request.request_method} " +
|
|
166
|
+
elsif Flapjack.logger.info?
|
|
167
|
+
Flapjack.logger.info("Returning #{response.status} for #{request.request_method} " +
|
|
258
168
|
"#{request.path_info}#{query_string}")
|
|
259
169
|
end
|
|
260
170
|
end
|
|
261
171
|
|
|
262
|
-
module Helpers
|
|
263
|
-
|
|
264
|
-
def cors_headers
|
|
265
|
-
allow_headers = %w(* Content-Type Accept AUTHORIZATION Cache-Control)
|
|
266
|
-
allow_methods = %w(GET POST PUT PATCH DELETE OPTIONS)
|
|
267
|
-
expose_headers = %w(Cache-Control Content-Language Content-Type Expires Last-Modified Pragma)
|
|
268
|
-
cors_headers = {
|
|
269
|
-
'Access-Control-Allow-Origin' => '*',
|
|
270
|
-
'Access-Control-Allow-Methods' => allow_methods.join(', '),
|
|
271
|
-
'Access-Control-Allow-Headers' => allow_headers.join(', '),
|
|
272
|
-
'Access-Control-Expose-Headers' => expose_headers.join(', '),
|
|
273
|
-
'Access-Control-Max-Age' => '1728000'
|
|
274
|
-
}
|
|
275
|
-
headers(cors_headers)
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
def err(status, *msg)
|
|
279
|
-
msg_str = msg.join(", ")
|
|
280
|
-
logger.info "Error: #{msg_str}"
|
|
281
|
-
[status, {}, Flapjack.dump_json(:errors => msg)]
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
def charset_for_content_type(ct)
|
|
285
|
-
"#{ct}; charset=#{Encoding.default_external}"
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
def is_json_request?
|
|
289
|
-
Flapjack::Gateways::JSONAPI::JSON_REQUEST_MIME_TYPES.include?(request.content_type.split(/\s*[;,]\s*/, 2).first)
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
def is_jsonapi_request?
|
|
293
|
-
return false if request.content_type.nil?
|
|
294
|
-
'application/vnd.api+json'.eql?(request.content_type.split(/\s*[;,]\s*/, 2).first)
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
def is_jsonpatch_request?
|
|
298
|
-
return false if request.content_type.nil?
|
|
299
|
-
'application/json-patch+json'.eql?(request.content_type.split(/\s*[;,]\s*/, 2).first)
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
def wrapped_params(name, error_on_nil = true)
|
|
303
|
-
result = params[name.to_sym]
|
|
304
|
-
if result.nil?
|
|
305
|
-
if error_on_nil
|
|
306
|
-
logger.debug("No '#{name}' object found in the following supplied JSON:")
|
|
307
|
-
logger.debug(request.body.is_a?(StringIO) ? request.body.read : request.body)
|
|
308
|
-
halt err(403, "No '#{name}' object received")
|
|
309
|
-
else
|
|
310
|
-
result = [{}]
|
|
311
|
-
end
|
|
312
|
-
end
|
|
313
|
-
unless result.is_a?(Array)
|
|
314
|
-
halt err(403, "The received '#{name}'' object is not an Array")
|
|
315
|
-
end
|
|
316
|
-
result
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
def find_contact(contact_id)
|
|
320
|
-
contact = Flapjack::Data::Contact.find_by_id(contact_id, :logger => logger, :redis => redis)
|
|
321
|
-
raise Flapjack::Gateways::JSONAPI::ContactNotFound.new(contact_id) if contact.nil?
|
|
322
|
-
contact
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
def find_rule(rule_id)
|
|
326
|
-
rule = Flapjack::Data::NotificationRule.find_by_id(rule_id, :logger => logger, :redis => redis)
|
|
327
|
-
raise Flapjack::Gateways::JSONAPI::NotificationRuleNotFound.new(rule_id) if rule.nil?
|
|
328
|
-
rule
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
def find_tags(tags)
|
|
332
|
-
halt err(400, "no tags given") if tags.nil? || tags.empty?
|
|
333
|
-
tags
|
|
334
|
-
end
|
|
335
|
-
|
|
336
|
-
def find_entity(entity_name)
|
|
337
|
-
entity = Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis)
|
|
338
|
-
raise Flapjack::Gateways::JSONAPI::EntityNotFound.new(entity_name) if entity.nil?
|
|
339
|
-
entity
|
|
340
|
-
end
|
|
341
|
-
|
|
342
|
-
def find_entity_by_id(entity_id)
|
|
343
|
-
entity = Flapjack::Data::Entity.find_by_id(entity_id, :redis => redis)
|
|
344
|
-
raise Flapjack::Gateways::JSONAPI::EntityNotFound.new(entity_id) if entity.nil?
|
|
345
|
-
entity
|
|
346
|
-
end
|
|
347
|
-
|
|
348
|
-
def find_entity_check(entity, check_name)
|
|
349
|
-
entity_check = Flapjack::Data::EntityCheck.for_entity(entity, check_name, :redis => redis)
|
|
350
|
-
raise Flapjack::Gateways::JSONAPI::EntityCheckNotFound.new(entity.name, check_name) if entity_check.nil?
|
|
351
|
-
entity_check
|
|
352
|
-
end
|
|
353
|
-
|
|
354
|
-
def find_entity_check_by_name(entity_name, check_name)
|
|
355
|
-
entity_check = Flapjack::Data::EntityCheck.for_entity_name(entity_name, check_name, :redis => redis)
|
|
356
|
-
raise Flapjack::Gateways::JSONAPI::EntityCheckNotFound.new(entity_name, check_name) if entity_check.nil?
|
|
357
|
-
entity_check
|
|
358
|
-
end
|
|
359
|
-
|
|
360
|
-
def apply_json_patch(object_path, &block)
|
|
361
|
-
ops = params[:ops]
|
|
362
|
-
|
|
363
|
-
if ops.nil? || !ops.is_a?(Array)
|
|
364
|
-
halt err(400, "Invalid JSON-Patch request")
|
|
365
|
-
end
|
|
366
|
-
|
|
367
|
-
ops.each do |operation|
|
|
368
|
-
linked = nil
|
|
369
|
-
property = nil
|
|
370
|
-
|
|
371
|
-
op = operation['op']
|
|
372
|
-
operation['path'] =~ /\A\/#{object_path}\/0\/([^\/]+)(?:\/([^\/]+)(?:\/([^\/]+))?)?\z/
|
|
373
|
-
if 'links'.eql?($1)
|
|
374
|
-
linked = $2
|
|
375
|
-
|
|
376
|
-
value = case op
|
|
377
|
-
when 'add'
|
|
378
|
-
operation['value']
|
|
379
|
-
when 'remove'
|
|
380
|
-
$3
|
|
381
|
-
end
|
|
382
|
-
elsif 'replace'.eql?(op)
|
|
383
|
-
property = $1
|
|
384
|
-
value = operation['value']
|
|
385
|
-
else
|
|
386
|
-
next
|
|
387
|
-
end
|
|
388
|
-
|
|
389
|
-
yield(op, property, linked, value)
|
|
390
|
-
end
|
|
391
|
-
end
|
|
392
|
-
|
|
393
|
-
# NB: casts to UTC before converting to a timestamp
|
|
394
|
-
def validate_and_parsetime(value)
|
|
395
|
-
return unless value
|
|
396
|
-
Time.iso8601(value).getutc.to_i
|
|
397
|
-
rescue ArgumentError => e
|
|
398
|
-
logger.error "Couldn't parse time from '#{value}'"
|
|
399
|
-
nil
|
|
400
|
-
end
|
|
401
|
-
|
|
402
|
-
end
|
|
403
|
-
|
|
404
172
|
options '*' do
|
|
405
173
|
cors_headers
|
|
406
174
|
204
|
|
407
175
|
end
|
|
408
176
|
|
|
177
|
+
# FIXME enforce that Accept header must allow defined return type for the method
|
|
178
|
+
|
|
409
179
|
# The following catch-all routes act as impromptu filters for their method types
|
|
410
180
|
get '*' do
|
|
411
|
-
content_type charset_for_content_type(JSONAPI_MEDIA_TYPE)
|
|
412
181
|
cors_headers
|
|
182
|
+
content_type media_type_produced(:with_charset => true)
|
|
413
183
|
pass
|
|
414
184
|
end
|
|
415
185
|
|
|
416
186
|
# bare 'params' may have splat/captures for regex route, see
|
|
417
187
|
# https://github.com/sinatra/sinatra/issues/453
|
|
418
188
|
post '*' do
|
|
419
|
-
halt(405) unless request.params.empty? ||
|
|
420
|
-
content_type charset_for_content_type(JSONAPI_MEDIA_TYPE)
|
|
189
|
+
halt(405) unless request.params.empty? || is_jsonapi_request?
|
|
421
190
|
cors_headers
|
|
191
|
+
content_type media_type_produced(:with_charset => true)
|
|
422
192
|
pass
|
|
423
193
|
end
|
|
424
194
|
|
|
425
195
|
patch '*' do
|
|
426
|
-
halt(405) unless
|
|
427
|
-
content_type charset_for_content_type(JSONAPI_MEDIA_TYPE)
|
|
196
|
+
halt(405) unless request.params.empty? || is_jsonapi_request?
|
|
428
197
|
cors_headers
|
|
198
|
+
content_type media_type_produced(:with_charset => true)
|
|
429
199
|
pass
|
|
430
200
|
end
|
|
431
201
|
|
|
@@ -434,21 +204,65 @@ module Flapjack
|
|
|
434
204
|
pass
|
|
435
205
|
end
|
|
436
206
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
207
|
+
include Swagger::Blocks
|
|
208
|
+
include Flapjack::Gateways::JSONAPI::Helpers::SwaggerDocs
|
|
209
|
+
|
|
210
|
+
# hacky, but trying to avoid too much boilerplate -- association paths
|
|
211
|
+
# must be before resource ones to avoid greedy path captures
|
|
212
|
+
%w[metrics association_post resource_post association_get resource_get
|
|
213
|
+
association_patch resource_patch association_delete
|
|
214
|
+
resource_delete].each do |method|
|
|
215
|
+
|
|
216
|
+
require "flapjack/gateways/jsonapi/methods/#{method}"
|
|
217
|
+
eval "register Flapjack::Gateways::JSONAPI::Methods::#{method.camelize}"
|
|
448
218
|
end
|
|
449
219
|
|
|
450
|
-
|
|
220
|
+
Flapjack::Gateways::JSONAPI::RESOURCE_CLASSES.each do |resource_class|
|
|
221
|
+
endpoint = resource_class.short_model_name.plural
|
|
222
|
+
swagger_wrappers(endpoint, resource_class)
|
|
223
|
+
end
|
|
451
224
|
|
|
452
|
-
|
|
225
|
+
SWAGGERED_CLASSES = [self] + Flapjack::Gateways::JSONAPI::RESOURCE_CLASSES +
|
|
226
|
+
[Flapjack::Data::Metrics]
|
|
453
227
|
|
|
228
|
+
get '/doc' do
|
|
229
|
+
Flapjack.dump_json(Swagger::Blocks.build_root_json(SWAGGERED_CLASSES))
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# error Zermelo::LockNotAcquired do
|
|
233
|
+
# # TODO
|
|
234
|
+
# end
|
|
235
|
+
|
|
236
|
+
error Zermelo::Records::Errors::RecordInvalid do
|
|
237
|
+
e = env['sinatra.error']
|
|
238
|
+
err(403, *e.record.errors.full_messages)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
error Zermelo::Records::Errors::RecordNotSaved do
|
|
242
|
+
e = env['sinatra.error']
|
|
243
|
+
err(403, *e.record.errors.full_messages)
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
error Zermelo::Records::Errors::RecordNotFound do
|
|
247
|
+
e = env['sinatra.error']
|
|
248
|
+
type = e.klass.name.split('::').last
|
|
249
|
+
err(404, "could not find #{type} record, id: '#{e.id}'")
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
error Zermelo::Records::Errors::RecordsNotFound do
|
|
253
|
+
e = env['sinatra.error']
|
|
254
|
+
type = e.klass.name.split('::').last
|
|
255
|
+
err_ids = e.ids.join("', '")
|
|
256
|
+
err(404, "could not find #{type} records, ids: '#{err_ids}'")
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
error do
|
|
260
|
+
e = env['sinatra.error']
|
|
261
|
+
# trace = e.backtrace.join("\n")
|
|
262
|
+
# puts trace
|
|
263
|
+
err(response.status, "#{e.class} - #{e.message}")
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
end
|
|
267
|
+
end
|
|
454
268
|
end
|