From 7cc933655a1416fb81641f16149ed6c0e362994c Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 19 Sep 2014 15:14:28 +0930 Subject: [PATCH 01/69] some pact specs for check functions --- .gitignore | 1 + .travis.yml | 2 +- Gemfile | 1 + Gemfile.lock | 19 +++ Rakefile | 1 + lib/flapjack/data/entity_check.rb | 4 +- lib/flapjack/gateways/jsonapi.rb | 69 ++++---- .../gateways/jsonapi/check_methods.rb | 4 +- spec/service_consumers/pact_helper.rb | 72 ++++++++ .../pacts/flapjack-diner_v1.0.json | 158 ++++++++++++++++++ .../provider_states_for_flapjack-diner.rb | 31 ++++ spec/spec_helper.rb | 2 - 12 files changed, 329 insertions(+), 35 deletions(-) create mode 100644 spec/service_consumers/pact_helper.rb create mode 100644 spec/service_consumers/pacts/flapjack-diner_v1.0.json create mode 100644 spec/service_consumers/provider_states_for_flapjack-diner.rb diff --git a/.gitignore b/.gitignore index 379e03391..343a21a89 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ vendor .bundle etc/*.yaml coverage +tmp/pacts tmp/cucumber_cli tmp/pids/* tmp/spec* diff --git a/.travis.yml b/.travis.yml index 4e8d74409..a8d273040 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ before_script: before_install: - git submodule update --init --recursive - gem install bundler -script: bundle exec rspec spec && bundle exec cucumber features +script: bundle exec rspec spec && bundle exec rake pact:verify && bundle exec cucumber features notifications: irc: channels: diff --git a/Gemfile b/Gemfile index 275ea91e1..98249ee45 100644 --- a/Gemfile +++ b/Gemfile @@ -11,6 +11,7 @@ group :test do gem 'cucumber' gem 'delorean' gem 'rack-test' + gem 'pact' gem 'async_rack_test', '>= 0.0.5' gem 'resque_spec' gem 'webmock' diff --git a/Gemfile.lock b/Gemfile.lock index 3fc842faf..2d18a3fca 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -36,6 +36,7 @@ GEM multi_json (~> 1.0) addressable (2.3.6) async_rack_test (0.0.5) + awesome_print (1.2.0) blather (0.8.8) activesupport (>= 2.3.11) eventmachine (>= 1.0.0) @@ -84,6 +85,7 @@ GEM eventmachine (>= 1.0.0.beta.1) eventmachine (1.0.3) ffi (1.9.3) + find_a_port (1.0.1) formatador (0.2.4) fuubar (2.0.0) rspec (~> 3.0) @@ -110,6 +112,7 @@ GEM http_parser.rb (0.6.0) i18n (0.6.11) ice_cube (0.12.1) + json (1.8.1) listen (2.4.0) celluloid (>= 0.15.2) rb-fsevent (>= 0.9.3) @@ -129,6 +132,16 @@ GEM mini_portile (= 0.6.0) numerizer (0.1.1) oj (2.10.1) + pact (1.3.2) + awesome_print (~> 1.1) + find_a_port (~> 1.0.1) + json + rack-test (~> 0.6.2) + randexp (~> 0.1.7) + rspec (>= 2.14) + term-ansicolor (~> 1.0) + thor + webrick perftools.rb (2.0.1) pry (0.9.12.4) coderay (~> 1.0) @@ -141,6 +154,7 @@ GEM rack-test (0.6.2) rack (>= 1.0) rake (10.3.2) + randexp (0.1.7) rb-fsevent (0.9.4) rb-inotify (0.9.3) ffi (>= 0.5.0) @@ -189,6 +203,8 @@ GEM rack-protection (~> 1.4) tilt (~> 1.3, >= 1.3.4) slop (3.4.7) + term-ansicolor (1.3.0) + tins (~> 1.0) terminal-table (1.4.5) thin (1.6.2) daemons (>= 1.0.9) @@ -197,6 +213,7 @@ GEM thor (0.18.1) tilt (1.4.1) timers (1.1.0) + tins (1.3.2) trollop (2.0) tzinfo (1.0.1) tzinfo-data (1.2014.6) @@ -206,6 +223,7 @@ GEM webmock (1.18.0) addressable (>= 2.3.6) crack (>= 0.3.2) + webrick (1.3.1) PLATFORMS ruby @@ -220,6 +238,7 @@ DEPENDENCIES guard guard-cucumber guard-rspec + pact perftools.rb rack-test rb-fsevent diff --git a/Rakefile b/Rakefile index 0c3d5650b..654cac04b 100644 --- a/Rakefile +++ b/Rakefile @@ -8,6 +8,7 @@ require 'fileutils' require 'rake' require 'resque/tasks' +require 'pact/tasks' Dir['tasks/**/*.rake'].each { |t| load t } diff --git a/lib/flapjack/data/entity_check.rb b/lib/flapjack/data/entity_check.rb index a706363d7..4d104e257 100755 --- a/lib/flapjack/data/entity_check.rb +++ b/lib/flapjack/data/entity_check.rb @@ -65,6 +65,7 @@ def self.for_event_id(event_id, options = {}) logger = options[:logger] entity = Flapjack::Data::Entity.find_by_name(entity_name, :create => create_entity, :logger => logger, :redis => redis) + return if entity.nil? self.new(entity, check_name, :logger => logger, :redis => redis) end @@ -94,7 +95,8 @@ def self.for_entity(entity, check, options = {}) def self.all(options = {}) raise "Redis connection not set" unless redis = options[:redis] - checks = redis.keys('check:*').map {|c| c.match(/^check:(.+)$/) ; $1} + checks = redis.keys('check:*').map {|c| c.match(/^check:(.+)$/) ; $1} | + find_current_names(:redis => redis) checks.map {|ec| self.for_event_id(ec, options) } diff --git a/lib/flapjack/gateways/jsonapi.rb b/lib/flapjack/gateways/jsonapi.rb index de770950f..c1c537b8a 100644 --- a/lib/flapjack/gateways/jsonapi.rb +++ b/lib/flapjack/gateways/jsonapi.rb @@ -89,6 +89,13 @@ def initialize(entity, check) end end + class EntityChecksNotFound < RuntimeError + attr_reader :entity_checks + def initialize(entity_checks) + @entity_checks = entity_checks + end + end + class ResourceLocked < RuntimeError attr_reader :resource def initialize(resource) @@ -100,37 +107,38 @@ def initialize(resource) set :protection, :except => :path_traversal - rescue_error = Proc.new {|status, exception, request_info, *msg| - if !msg || msg.empty? - trace = exception.backtrace.join("\n") - msg = "#{exception.class} - #{exception.message}" - msg_str = "#{msg}\n#{trace}" - else - msg_str = msg.join(", ") - end - case - when status < 500 - @logger.warn "Error: #{msg_str}" - else - @logger.error "Error: #{msg_str}" - end + @rescue_exception = Proc.new {|env, e| + + rescue_error = Proc.new {|status, exception, request_info, *msg| + if !msg || msg.empty? + trace = exception.backtrace.join("\n") + msg = "#{exception.class} - #{exception.message}" + msg_str = "#{msg}\n#{trace}" + else + msg_str = msg.join(", ") + end + case + when status < 500 + @logger.warn "Error: #{msg_str}" + else + @logger.error "Error: #{msg_str}" + end - response_body = {:errors => msg}.to_json + response_body = {:errors => msg}.to_json - query_string = (request_info[:query_string].respond_to?(:length) && - request_info[:query_string].length > 0) ? "?#{request_info[:query_string]}" : "" - if @logger.debug? - @logger.debug("Returning #{status} for #{request_info[:request_method]} " + - "#{request_info[:path_info]}#{query_string}, body: #{response_body}") - elsif @logger.info? - @logger.info("Returning #{status} for #{request_info[:request_method]} " + - "#{request_info[:path_info]}#{query_string}") - end + query_string = (request_info[:query_string].respond_to?(:length) && + request_info[:query_string].length > 0) ? "?#{request_info[:query_string]}" : "" + if @logger.debug? + @logger.debug("Returning #{status} for #{request_info[:request_method]} " + + "#{request_info[:path_info]}#{query_string}, body: #{response_body}") + elsif @logger.info? + @logger.info("Returning #{status} for #{request_info[:request_method]} " + + "#{request_info[:path_info]}#{query_string}") + end - [status, {}, response_body] - } + [status, {}, response_body] + } - rescue_exception = Proc.new {|env, e| request_info = { :path_info => env['REQUEST_PATH'], :request_method => env['REQUEST_METHOD'], @@ -149,13 +157,16 @@ def initialize(resource) rescue_error.call(404, e, request_info, "could not find entity '#{e.entity}'") when Flapjack::Gateways::JSONAPI::EntityCheckNotFound rescue_error.call(404, e, request_info, "could not find entity check '#{e.check}'") + when Flapjack::Gateways::JSONAPI::EntityChecksNotFound + checks = "'" + e.entity_checks.join("', '") + "'" + rescue_error.call(404, e, request_info, "could not find entity checks: #{checks}") when Flapjack::Gateways::JSONAPI::ResourceLocked rescue_error.call(423, e, request_info, "unable to obtain lock for resource '#{e.resource}'") else rescue_error.call(500, e, request_info) end } - use ::Rack::FiberPool, :size => 25, :rescue_exception => rescue_exception + use ::Rack::FiberPool, :size => 25, :rescue_exception => @rescue_exception use ::Rack::MethodOverride use Flapjack::Gateways::JSONAPI::Rack::JsonParamsParser @@ -205,7 +216,7 @@ def base_url before do input = nil query_string = (request.query_string.respond_to?(:length) && - request.query_string.length > 0) ? "?#{request.query_string}" : "" + (request.query_string.length > 0)) ? "?#{request.query_string}" : "" if logger.debug? input = env['rack.input'].read logger.debug("#{request.request_method} #{request.path_info}#{query_string} #{input}") diff --git a/lib/flapjack/gateways/jsonapi/check_methods.rb b/lib/flapjack/gateways/jsonapi/check_methods.rb index 7a464b27f..3e6fbe55b 100644 --- a/lib/flapjack/gateways/jsonapi/check_methods.rb +++ b/lib/flapjack/gateways/jsonapi/check_methods.rb @@ -48,7 +48,7 @@ def self.registered(app) checks.compact! if requested_checks && checks.empty? - raise Flapjack::Gateways::JSONAPI::ChecksNotFound.new(requested_checks) + raise Flapjack::Gateways::JSONAPI::EntityChecksNotFound.new(requested_checks) end check_ids = checks.collect {|c| "#{c.entity.name}:#{c.check}" } @@ -57,7 +57,7 @@ def self.registered(app) linked_entity_ids = checks.empty? ? [] : checks.inject({}) do |memo, check| entity = check.entity - memo["#{entity.name}:#{check.check}"] = entity.id + memo["#{entity.name}:#{check.check}"] = [entity.id] memo end diff --git a/spec/service_consumers/pact_helper.rb b/spec/service_consumers/pact_helper.rb new file mode 100644 index 000000000..1085b98b2 --- /dev/null +++ b/spec/service_consumers/pact_helper.rb @@ -0,0 +1,72 @@ +require 'pact/provider/rspec' + +require 'flapjack/configuration' +require 'flapjack/gateways/jsonapi' + +require './spec/service_consumers/provider_states_for_flapjack-diner.rb' + +$testing = true + +FLAPJACK_ENV = ENV["FLAPJACK_ENV"] || 'test' +FLAPJACK_ROOT = File.join(File.dirname(__FILE__), '..') +FLAPJACK_CONFIG = File.join(FLAPJACK_ROOT, 'etc', 'flapjack_config.yaml') +ENV['RACK_ENV'] = ENV["FLAPJACK_ENV"] + +require 'bundler' +Bundler.require(:default, :test) + +class MockLogger + attr_accessor :messages + + def initialize + @messages = [] + end + + %w(debug info warn error fatal).each do |level| + class_eval <<-RUBY + def #{level}? + true + end + + def #{level}(msg) + @messages << msg + end + RUBY + end +end + +Pact.configure do |config| + cfg = Flapjack::Configuration.new + $redis_options = cfg.load(FLAPJACK_CONFIG) ? + cfg.for_redis : + {:db => 14, :driver => :ruby} + + Flapjack::Gateways::JSONAPI.instance_variable_set('@config', 'port' => 19081) + + Flapjack::Gateways::JSONAPI.instance_variable_set('@redis_config', $redis_options) + Flapjack::Gateways::JSONAPI.instance_variable_set('@logger', MockLogger.new) + + Flapjack::Gateways::JSONAPI.instance_variable_get('@middleware').delete_if {|m| + m[0] == Rack::FiberPool + } + + Flapjack::Gateways::JSONAPI.class_eval do + set :show_exceptions, false + error do + Flapjack::Gateways::JSONAPI.instance_variable_get('@rescue_exception'). + call(env, env['sinatra.error']) + end + end + + Flapjack::Gateways::JSONAPI.start + +end + +Pact.service_provider "flapjack" do + + app { Flapjack::Gateways::JSONAPI.new } + + honours_pact_with 'flapjack-diner' do + pact_uri './spec/service_consumers/pacts/flapjack-diner_v1.0.json' + end +end \ No newline at end of file diff --git a/spec/service_consumers/pacts/flapjack-diner_v1.0.json b/spec/service_consumers/pacts/flapjack-diner_v1.0.json new file mode 100644 index 000000000..31a2a2ad9 --- /dev/null +++ b/spec/service_consumers/pacts/flapjack-diner_v1.0.json @@ -0,0 +1,158 @@ +{ + "provider": { + "name": "flapjack" + }, + "consumer": { + "name": "flapjack-diner" + }, + "interactions": [ + { + "description": "a GET request for all checks", + "provider_state": "no entity exists", + "request": { + "method": "get", + "path": "/checks" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "checks": [ + + ] + } + } + }, + { + "description": "a GET request for all checks", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/checks" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "checks": [ + { + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } + } + ] + } + } + }, + { + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/checks/www.example.com:SSH" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "checks": [ + { + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } + } + ] + } + } + }, + { + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "no entity exists", + "request": { + "method": "get", + "path": "/checks/www.example.com:SSH" + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity checks: 'www.example.com:SSH'" + ] + } + } + }, + { + "description": "a PATCH request for a single check", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "patch", + "path": "/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/checks/0/enabled", + "value": false + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for a single check", + "provider_state": "no entity exists", + "request": { + "method": "patch", + "path": "/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/checks/0/enabled", + "value": false + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } + } + } + ], + "metadata": { + "pactSpecificationVersion": "1.0.0" + } +} \ No newline at end of file diff --git a/spec/service_consumers/provider_states_for_flapjack-diner.rb b/spec/service_consumers/provider_states_for_flapjack-diner.rb new file mode 100644 index 000000000..e4a3b8980 --- /dev/null +++ b/spec/service_consumers/provider_states_for_flapjack-diner.rb @@ -0,0 +1,31 @@ +Pact.provider_states_for "flapjack-diner" do + + provider_state "no entity exists" do + set_up do + end + + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end + + provider_state "a check 'www.example.com:SSH' exists" do + set_up do + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + + entity_data = {'id' => '1234', 'name' => 'www.example.com'} + Flapjack::Data::Entity.add(entity_data, :redis => redis) + check_data = {'entity_id' => '1234', 'name' => 'SSH'} + Flapjack::Data::EntityCheck.add(check_data, :redis => redis) + end + + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end + +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 61ee8be50..78ff15db4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -70,8 +70,6 @@ def #{level}? end - - # This file was generated by the `rspec --init` command. Conventionally, all # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. # Require this file using `require "spec_helper"` to ensure that it is only From 6d21ee826f7bd592d0a38ed68980c5a0ca5f1341 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 19 Sep 2014 15:34:50 +0930 Subject: [PATCH 02/69] pacts pass locally, fail on travis --- spec/service_consumers/pact_helper.rb | 46 ++++++++++++++------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/spec/service_consumers/pact_helper.rb b/spec/service_consumers/pact_helper.rb index 1085b98b2..c90ef4d4f 100644 --- a/spec/service_consumers/pact_helper.rb +++ b/spec/service_consumers/pact_helper.rb @@ -35,30 +35,32 @@ def #{level}(msg) end end -Pact.configure do |config| - cfg = Flapjack::Configuration.new - $redis_options = cfg.load(FLAPJACK_CONFIG) ? - cfg.for_redis : - {:db => 14, :driver => :ruby} - - Flapjack::Gateways::JSONAPI.instance_variable_set('@config', 'port' => 19081) - - Flapjack::Gateways::JSONAPI.instance_variable_set('@redis_config', $redis_options) - Flapjack::Gateways::JSONAPI.instance_variable_set('@logger', MockLogger.new) - - Flapjack::Gateways::JSONAPI.instance_variable_get('@middleware').delete_if {|m| - m[0] == Rack::FiberPool - } - - Flapjack::Gateways::JSONAPI.class_eval do - set :show_exceptions, false - error do - Flapjack::Gateways::JSONAPI.instance_variable_get('@rescue_exception'). - call(env, env['sinatra.error']) - end +Flapjack::Gateways::JSONAPI.instance_variable_get('@middleware').delete_if {|m| + m[0] == Rack::FiberPool +} + +Flapjack::Gateways::JSONAPI.class_eval do + set :show_exceptions, false + set :raise_errors, false + error do + Flapjack::Gateways::JSONAPI.instance_variable_get('@rescue_exception'). + call(env, env['sinatra.error']) end +end + +cfg = Flapjack::Configuration.new +$redis_options = cfg.load(FLAPJACK_CONFIG) ? + cfg.for_redis : + {:db => 14, :driver => :ruby} + +Flapjack::Gateways::JSONAPI.instance_variable_set('@config', 'port' => 19081) - Flapjack::Gateways::JSONAPI.start +Flapjack::Gateways::JSONAPI.instance_variable_set('@redis_config', $redis_options) +Flapjack::Gateways::JSONAPI.instance_variable_set('@logger', MockLogger.new) + +Flapjack::Gateways::JSONAPI.start + +Pact.configure do |config| end From a6ee29b55e3569d912a46cc722610b693f87849e Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 19 Sep 2014 16:30:14 +0930 Subject: [PATCH 03/69] fix check create pacts --- lib/flapjack/gateways/jsonapi.rb | 2 +- .../pacts/flapjack-diner_v1.0.json | 103 ++++++++++++++---- .../provider_states_for_flapjack-diner.rb | 15 +++ 3 files changed, 98 insertions(+), 22 deletions(-) diff --git a/lib/flapjack/gateways/jsonapi.rb b/lib/flapjack/gateways/jsonapi.rb index c1c537b8a..81f4cca93 100644 --- a/lib/flapjack/gateways/jsonapi.rb +++ b/lib/flapjack/gateways/jsonapi.rb @@ -401,7 +401,7 @@ def validate_and_parsetime(value) # bare 'params' may have splat/captures for regex route, see # https://github.com/sinatra/sinatra/issues/453 post '*' do - halt(405) unless request.params.empty? || is_json_request? || is_jsonapi_request + halt(405) unless request.params.empty? || is_json_request? || is_jsonapi_request? content_type JSONAPI_MEDIA_TYPE cors_headers pass diff --git a/spec/service_consumers/pacts/flapjack-diner_v1.0.json b/spec/service_consumers/pacts/flapjack-diner_v1.0.json index 31a2a2ad9..af2a2e65f 100644 --- a/spec/service_consumers/pacts/flapjack-diner_v1.0.json +++ b/spec/service_consumers/pacts/flapjack-diner_v1.0.json @@ -7,30 +7,30 @@ }, "interactions": [ { - "description": "a GET request for all checks", + "description": "a GET request for check 'www.example.com:SSH'", "provider_state": "no entity exists", "request": { "method": "get", - "path": "/checks" + "path": "/checks/www.example.com:SSH" }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ - + "errors": [ + "could not find entity checks: 'www.example.com:SSH'" ] } } }, { - "description": "a GET request for all checks", + "description": "a GET request for check 'www.example.com:SSH'", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/checks" + "path": "/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -54,11 +54,11 @@ } }, { - "description": "a GET request for check 'www.example.com:SSH'", + "description": "a GET request for all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/checks/www.example.com:SSH" + "path": "/checks" }, "response": { "status": 200, @@ -82,27 +82,27 @@ } }, { - "description": "a GET request for check 'www.example.com:SSH'", + "description": "a GET request for all checks", "provider_state": "no entity exists", "request": { "method": "get", - "path": "/checks/www.example.com:SSH" + "path": "/checks" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find entity checks: 'www.example.com:SSH'" + "checks": [ + ] } } }, { "description": "a PATCH request for a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "provider_state": "no entity exists", "request": { "method": "patch", "path": "/checks/www.example.com:SSH", @@ -118,13 +118,20 @@ ] }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { "description": "a PATCH request for a single check", - "provider_state": "no entity exists", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "patch", "path": "/checks/www.example.com:SSH", @@ -140,15 +147,69 @@ ] }, "response": { - "status": 404, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two checks", + "provider_state": "an entity 'www.example.com' exists", + "request": { + "method": "post", + "path": "/checks", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "checks": [ + { + "name": "SSH", + "entity_id": "1234" + }, + { + "name": "PING", + "entity_id": "1234" + } + ] + } + }, + "response": { + "status": 201, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, + "body": [ + "www.example.com:SSH", + "www.example.com:PING" + ] + } + }, + { + "description": "a POST request with one check", + "provider_state": "an entity 'www.example.com' exists", + "request": { + "method": "post", + "path": "/checks", + "headers": { + "Content-Type": "application/vnd.api+json" + }, "body": { - "errors": [ - "could not find entity 'www.example.com'" + "checks": [ + { + "name": "PING", + "entity_id": "1234" + } ] } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:PING" + ] } } ], diff --git a/spec/service_consumers/provider_states_for_flapjack-diner.rb b/spec/service_consumers/provider_states_for_flapjack-diner.rb index e4a3b8980..a7c670ce6 100644 --- a/spec/service_consumers/provider_states_for_flapjack-diner.rb +++ b/spec/service_consumers/provider_states_for_flapjack-diner.rb @@ -11,6 +11,21 @@ end end + provider_state "an entity 'www.example.com' exists" do + set_up do + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + + entity_data = {'id' => '1234', 'name' => 'www.example.com'} + Flapjack::Data::Entity.add(entity_data, :redis => redis) + end + + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end + provider_state "a check 'www.example.com:SSH' exists" do set_up do redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') From 25f239cd73ddb213ebe977efeedacc0cec5861f6 Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Sat, 20 Sep 2014 10:28:51 -0700 Subject: [PATCH 04/69] fixes #619 with a location.reload, sorry world --- lib/flapjack/gateways/web/public/js/flapjack.js | 3 ++- lib/flapjack/gateways/web/public/js/modules/contact.js | 3 ++- lib/flapjack/gateways/web/views/edit_contacts.html.erb | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/flapjack/gateways/web/public/js/flapjack.js b/lib/flapjack/gateways/web/public/js/flapjack.js index 67fb7e48d..9f9265e90 100644 --- a/lib/flapjack/gateways/web/public/js/flapjack.js +++ b/lib/flapjack/gateways/web/public/js/flapjack.js @@ -49,6 +49,7 @@ $(document).ready(function() { $('div.modal-dialog').append(contactDetailsView.$el); $('#contactModal').modal('show'); + console.warn("foo"); } }); @@ -75,4 +76,4 @@ $(document).ready(function() { } }); -}); \ No newline at end of file +}); diff --git a/lib/flapjack/gateways/web/public/js/modules/contact.js b/lib/flapjack/gateways/web/public/js/modules/contact.js index 2b08f1d58..69a4eeb66 100644 --- a/lib/flapjack/gateways/web/public/js/modules/contact.js +++ b/lib/flapjack/gateways/web/public/js/modules/contact.js @@ -55,7 +55,8 @@ tagName: 'tbody', id: 'contactList', initialize: function() { - this.collection.on('add', this.render, this); + // FIXME: #619 dirty fix... + this.collection.on('add', location.reload, location); this.collection.on('remove', this.render, this); }, render: function() { diff --git a/lib/flapjack/gateways/web/views/edit_contacts.html.erb b/lib/flapjack/gateways/web/views/edit_contacts.html.erb index b8c6e6797..3d28e36d3 100644 --- a/lib/flapjack/gateways/web/views/edit_contacts.html.erb +++ b/lib/flapjack/gateways/web/views/edit_contacts.html.erb @@ -20,13 +20,13 @@ <@- first_name @> <@- last_name @> - + - + - + From 4f9def5970360f8c31e88d9c6d8905c4036b39b8 Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Sat, 20 Sep 2014 10:32:14 -0700 Subject: [PATCH 05/69] remove debug --- lib/flapjack/gateways/web/public/js/flapjack.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/flapjack/gateways/web/public/js/flapjack.js b/lib/flapjack/gateways/web/public/js/flapjack.js index 9f9265e90..1ff53a0c4 100644 --- a/lib/flapjack/gateways/web/public/js/flapjack.js +++ b/lib/flapjack/gateways/web/public/js/flapjack.js @@ -49,7 +49,6 @@ $(document).ready(function() { $('div.modal-dialog').append(contactDetailsView.$el); $('#contactModal').modal('show'); - console.warn("foo"); } }); From a20cccbe5096f3a9afe7704c218eea24aaf9276c Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Sat, 20 Sep 2014 10:46:30 -0700 Subject: [PATCH 06/69] tie ruby 2.1 to 2.1.2 while perftools.rb problem is sorted out --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4e8d74409..3cd5509ce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: ruby rvm: - 1.9.3 - '2.0' -- '2.1' +- '2.1.2' gemfile: - Gemfile services: From 6bd89927d564040ad00da5c7db7433aaf805aa2c Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Mon, 22 Sep 2014 15:44:22 +0930 Subject: [PATCH 07/69] optimise tag code --- lib/flapjack/data/contact.rb | 23 +------- lib/flapjack/data/entity.rb | 15 +---- lib/flapjack/data/entity_check.rb | 46 ++++------------ lib/flapjack/data/event.rb | 3 +- lib/flapjack/data/notification.rb | 2 +- lib/flapjack/data/notification_rule.rb | 13 ++--- lib/flapjack/data/tag.rb | 61 --------------------- lib/flapjack/data/tag_set.rb | 16 ------ lib/flapjack/data/tagged.rb | 58 ++++++++++++++++++++ lib/flapjack/processor.rb | 2 +- lib/flapjack/tagged.rb | 45 --------------- spec/lib/flapjack/data/contact_spec.rb | 16 ++---- spec/lib/flapjack/data/entity_check_spec.rb | 4 +- spec/lib/flapjack/data/event_spec.rb | 2 +- spec/lib/flapjack/data/tag_spec.rb | 36 ------------ 15 files changed, 88 insertions(+), 254 deletions(-) delete mode 100644 lib/flapjack/data/tag.rb delete mode 100644 lib/flapjack/data/tag_set.rb create mode 100644 lib/flapjack/data/tagged.rb delete mode 100644 lib/flapjack/tagged.rb delete mode 100644 spec/lib/flapjack/data/tag_spec.rb diff --git a/lib/flapjack/data/contact.rb b/lib/flapjack/data/contact.rb index a17981a08..fdfbc9070 100644 --- a/lib/flapjack/data/contact.rb +++ b/lib/flapjack/data/contact.rb @@ -7,8 +7,6 @@ require 'ice_cube' require 'flapjack/data/entity' require 'flapjack/data/notification_rule' -require 'flapjack/data/tag' -require 'flapjack/data/tag_set' require 'securerandom' @@ -18,8 +16,6 @@ module Data class Contact - include Tagged - attr_accessor :id, :first_name, :last_name, :email, :media, :media_intervals, :media_rollup_thresholds, :pagerduty_credentials @@ -79,10 +75,6 @@ def self.add(contact_data, options = {}) contact = self.find_by_id(contact_id, :redis => redis) unless contact.nil? - if contact_data['tags'] && contact_data['tags'].respond_to?(:each) - contact.add_tags(*contact_data['tags']) - end - contact.notification_rules # invoke to create general rule end @@ -116,12 +108,6 @@ def refresh def update(contact_data) self.class.add_or_update(@id, contact_data, :redis => @redis) - - if contact_data['tags'] && contact_data['tags'].respond_to?(:each) - self.delete_tags(*self.tags.to_a) - self.add_tags(*contact_data['tags']) - end - self.refresh end @@ -142,9 +128,6 @@ def delete! # the main alerts sorted set, remove all alerts_by sorted sets # for the contact - # remove this contact from all tags it's marked with - self.delete_tags(*self.tags.to_a) - # remove all associated notification rules self.notification_rules.each do |nr| self.delete_notification_rule(nr) @@ -266,8 +249,8 @@ def notification_rules(opts = {}) rule = self.add_notification_rule({ :entities => [], :regex_entities => [], - :tags => Flapjack::Data::TagSet.new([]), - :regex_tags => Flapjack::Data::TagSet.new([]), + :tags => Set.new([]), + :regex_tags => Set.new([]), :time_restrictions => [], :warning_media => ALL_MEDIA, :critical_media => ALL_MEDIA, @@ -480,7 +463,6 @@ def to_json(*args) "media_intervals" => self.media_intervals, "media_rollup_thresholds" => self.media_rollup_thresholds, "timezone" => self.timezone.name, - "tags" => self.tags.to_a }.to_json end @@ -490,7 +472,6 @@ def to_jsonapi(opts = {}) "last_name" => self.last_name, "email" => self.email, "timezone" => self.timezone.name, - "tags" => self.tags.to_a, "links" => { :entities => opts[:entity_ids] || [], :media => self.media_ids || [], diff --git a/lib/flapjack/data/entity.rb b/lib/flapjack/data/entity.rb index dacd9fd29..81075bd7c 100644 --- a/lib/flapjack/data/entity.rb +++ b/lib/flapjack/data/entity.rb @@ -2,9 +2,8 @@ require 'securerandom' -require 'flapjack/tagged' - require 'flapjack/data/contact' +require 'flapjack/data/tagged' module Flapjack @@ -513,18 +512,6 @@ def self.find_all_name_matching(pattern, options = {}) }.sort end - # # Not used anywhere - # def self.find_all_with_tags(tags, options = {}) - # raise "Redis connection not set" unless redis = options[:redis] - # tags_prefixed = tags.collect {|tag| - # "#{TAG_PREFIX}:#{tag}" - # } - # logger.debug "tags_prefixed: #{tags_prefixed.inspect}" if logger = options[:logger] - # Flapjack::Data::Tag.find_intersection(tags_prefixed, :redis => redis).collect {|entity_id| - # Flapjack::Data::Entity.find_by_id(entity_id, :redis => redis) - # }.compact - # end - def self.current_names(options = {}) raise "Redis connection not set" unless redis = options[:redis] redis.zrange('current_entities', 0, -1) diff --git a/lib/flapjack/data/entity_check.rb b/lib/flapjack/data/entity_check.rb index 61cb44cf2..9e0c3c079 100755 --- a/lib/flapjack/data/entity_check.rb +++ b/lib/flapjack/data/entity_check.rb @@ -7,6 +7,8 @@ require 'flapjack/data/contact' require 'flapjack/data/event' require 'flapjack/data/entity' +require 'flapjack/data/tagged' + #FIXME: Require chronic_duration in the correct place require 'chronic_duration' @@ -27,7 +29,7 @@ class EntityCheck NOTIFICATION_STATES = [:problem, :warning, :critical, :unknown, :recovery, :acknowledgement] - TAG_PREFIX = 'check_tag' + include Tagged attr_accessor :entity, :check @@ -168,18 +170,6 @@ def self.unacknowledged_failing(options = {}) } end - # # Not used anywhere - # def self.find_all_with_tags(tags, options = {}) - # raise "Redis connection not set" unless redis = options[:redis] - # tags_prefixed = tags.collect {|tag| - # "#{TAG_PREFIX}:#{tag}" - # } - # logger.debug "tags_prefixed: #{tags_prefixed.inspect}" if logger = options[:logger] - # Flapjack::Data::Tag.find_intersection(tags_prefixed, :redis => redis).collect {|event_id| - # Flapjack::Data::EntityCheck.find_by_id(event_id, :redis => redis) - # }.compact - # end - def self.conflate_to_keys(entity_checks_hash) result = [] entity_checks_hash.each {|entity, checks| @@ -911,13 +901,13 @@ def contacts }.compact end - def tags - @tags ||= Flapjack::Data::TagSet.new( @redis.keys("#{TAG_PREFIX}:*").inject([]) {|memo, check_tag| - if Flapjack::Data::Tag.find(check_tag, :redis => @redis).include?(@key) - memo << check_tag.sub(/^#{TAG_PREFIX}:/, '') - end - memo - } ) + # override default, which would be 'entity_check_tag' + def tag_prefix + 'check_tag' + end + + def tags_with_entity_and_check_name + tags_without_entity_and_check_name # ensure that returned tags include split entity and check words @tags += @entity.name.split('.', 2).map {|x| x.downcase} + @@ -926,20 +916,8 @@ def tags @tags end - def add_tags(*enum) - enum.each do |t| - Flapjack::Data::Tag.create("#{TAG_PREFIX}:#{t}", [@key], :redis => @redis) - tags.add(t) - end - end - - def delete_tags(*enum) - enum.each do |t| - tag = Flapjack::Data::Tag.find("#{TAG_PREFIX}:#{t}", :redis => @redis) - tag.delete(@key) - tags.delete(t) - end - end + alias_method :tags_without_entity_and_check_name, :tags + alias_method :tags, :tags_with_entity_and_check_name def ack_hash @ack_hash ||= @redis.hget('check_hashes_by_id', @key) diff --git a/lib/flapjack/data/event.rb b/lib/flapjack/data/event.rb index df3999230..71633588d 100755 --- a/lib/flapjack/data/event.rb +++ b/lib/flapjack/data/event.rb @@ -1,7 +1,6 @@ #!/usr/bin/env ruby require 'oj' -require 'flapjack/data/tag_set' module Flapjack module Data @@ -220,7 +219,7 @@ def initialize(attrs = {}) # perfdata is optional. set it to nil if it only contains whitespace @perfdata = (@perfdata.is_a?(String) && ! @perfdata.strip.empty?) ? @perfdata.strip : nil if attrs['tags'] - @tags = Flapjack::Data::TagSet.new + @tags = Set.new attrs['tags'].each {|tag| @tags.add(tag)} end end diff --git a/lib/flapjack/data/notification.rb b/lib/flapjack/data/notification.rb index 152444a90..ac1a63473 100644 --- a/lib/flapjack/data/notification.rb +++ b/lib/flapjack/data/notification.rb @@ -264,7 +264,7 @@ def initialize(opts = {}) @state_duration = opts['state_duration'] @type = opts['type'] @severity = opts['severity'] - @tags = opts['tags'].is_a?(Array) ? Flapjack::Data::TagSet.new(opts['tags']) : nil + @tags = opts['tags'].is_a?(Array) ? Set.new(opts['tags']) : nil end # # time restrictions match? diff --git a/lib/flapjack/data/notification_rule.rb b/lib/flapjack/data/notification_rule.rb index 25eab36f1..201bc7bd6 100644 --- a/lib/flapjack/data/notification_rule.rb +++ b/lib/flapjack/data/notification_rule.rb @@ -4,7 +4,6 @@ require 'active_support/time' require 'ice_cube' require 'flapjack/utility' -require 'flapjack/data/tag_set' module Flapjack module Data @@ -203,10 +202,10 @@ def self.preen(rule_data) rule_data[:warning_blackhole] = rule_data[:warning_blackhole] || false rule_data[:critical_blackhole] = rule_data[:critical_blackhole] || false if rule_data[:tags].is_a?(Array) - rule_data[:tags] = Flapjack::Data::TagSet.new(rule_data[:tags]) + rule_data[:tags] = Set.new(rule_data[:tags]) end if rule_data[:regex_tags].is_a?(Array) - rule_data[:regex_tags] = Flapjack::Data::TagSet.new(rule_data[:regex_tags]) + rule_data[:regex_tags] = Set.new(rule_data[:regex_tags]) end rule_data end @@ -323,13 +322,13 @@ def self.prepare_time_restriction(time_restriction, timezone = nil) proc {|d| !d.has_key?(:tags) || ( d[:tags].nil? || - d[:tags].is_a?(Flapjack::Data::TagSet) && + d[:tags].is_a?(Set) && d[:tags].all? {|et| et.is_a?(String)} ) } => "tags must be a tag_set of strings", proc {|d| !d.has_key?(:regex_tags) || ( d[:regex_tags].nil? || - d[:regex_tags].is_a?(Flapjack::Data::TagSet) && + d[:regex_tags].is_a?(Set) && d[:regex_tags].all? {|et| et.is_a?(String)} ) } => "regex_tags must be a tag_set of strings", @@ -401,9 +400,9 @@ def refresh @contact_id = rule_data['contact_id'] tags = Oj.load(rule_data['tags'] || '') - @tags = tags ? Flapjack::Data::TagSet.new(tags) : nil + @tags = tags ? Set.new(tags) : nil regex_tags = Oj.load(rule_data['regex_tags'] || '') - @regex_tags = regex_tags ? Flapjack::Data::TagSet.new(regex_tags) : nil + @regex_tags = regex_tags ? Set.new(regex_tags) : nil @entities = Oj.load(rule_data['entities'] || '') @regex_entities = Oj.load(rule_data['regex_entities'] || '') @time_restrictions = Oj.load(rule_data['time_restrictions'] || '') diff --git a/lib/flapjack/data/tag.rb b/lib/flapjack/data/tag.rb deleted file mode 100644 index 9f97a686b..000000000 --- a/lib/flapjack/data/tag.rb +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env ruby - -require 'set' -require 'redis' - -module Flapjack - module Data - - class Tag < ::Set - - attr_accessor :name - - def initialize(opts = {}) - raise "Redis connection not set" unless @redis = opts[:redis] - - @name = opts[:name] - preset = @redis.smembers(@name) - enum = opts[:create] || [] - @redis.sadd(@name, enum) unless enum.empty? - super(enum | preset) - end - - def self.find(name, opts) - self.new(:name => name, - :redis => opts[:redis]) - end - - def self.find_intersection(tags, opts) - @redis = opts[:redis] - @redis.sinter(tags) - end - - def self.create(name, enum = [], opts) - self.new(:name => name, - :create => enum, - :redis => opts[:redis]) - end - - def add(o) - @redis.sadd(@name, o) unless o.empty? - super(o) - end - - def delete(o) - @redis.srem(@name, o) - super(o) - end - - def merge(o) - @redis.sadd(@name, o) unless o.empty? - super(o) - end - - def to_json(*a) - self.to_a.to_json(*a) - end - - end - end -end - diff --git a/lib/flapjack/data/tag_set.rb b/lib/flapjack/data/tag_set.rb deleted file mode 100644 index 1b545c36c..000000000 --- a/lib/flapjack/data/tag_set.rb +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env ruby - -require 'set' - -module Flapjack - module Data - class TagSet < ::Set - - def to_json(*a) - self.to_a.to_json(*a) - end - - end - end -end - diff --git a/lib/flapjack/data/tagged.rb b/lib/flapjack/data/tagged.rb new file mode 100644 index 000000000..b6e1b9623 --- /dev/null +++ b/lib/flapjack/data/tagged.rb @@ -0,0 +1,58 @@ +#!/usr/bin/env ruby + +# mixed in to some of the Flapjack data classes + +module Flapjack + + module Tagged + + def tag_prefix + self.class.name.split('::').last.downcase + '_tag' + end + + def known_key + "known_tags:#{tag_prefix}" + end + + def known_tags + if @redis.scard(known_key) == 0 + discovered = @redis.keys("#{tag_prefix}:*") + @redis.sadd(known_key, discovered) unless discovered.empty? + discovered + else + @redis.smembers(known_key) + end + end + + # return the set of tags for this object + def tags + return @tags unless @tags.nil? + @tags ||= Set.new( known_tags.inject([]) {|memo, t| + tag_key = "#{tag_prefix}:#{t}" + memo << t if @redis.sismember(tag_key, @id.to_s) + memo + }) + end + + # adds tags to this object + def add_tags(*enum) + enum.each do |t| + @redis.sadd(known_key, t) + @redis.sadd("#{tag_prefix}:#{t}", @id) + tags.add(t) + end + end + + # removes tags from this object + def delete_tags(*enum) + enum.each do |t| + tag_key = "#{tag_prefix}:#{t}" + @redis.srem(tag_key, @id) + tags.delete(t) + @redis.srem(known_key, t) if (@redis.scard(tag_key) == 0) + end + end + + end + +end \ No newline at end of file diff --git a/lib/flapjack/processor.rb b/lib/flapjack/processor.rb index 7097fe9fb..22d6a0013 100755 --- a/lib/flapjack/processor.rb +++ b/lib/flapjack/processor.rb @@ -151,7 +151,7 @@ def process_event(event) entity_check = Flapjack::Data::EntityCheck.for_event_id(event.id, :create_entity => true, :redis => @redis) timestamp = Time.now.to_i - event.tags = (event.tags || Flapjack::Data::TagSet.new) + entity_check.tags + event.tags = (event.tags || Set.new) + entity_check.tags should_notify, previous_state = update_keys(event, entity_check, timestamp) diff --git a/lib/flapjack/tagged.rb b/lib/flapjack/tagged.rb deleted file mode 100644 index 499259282..000000000 --- a/lib/flapjack/tagged.rb +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env ruby - -require 'flapjack/data/tag' -require 'flapjack/data/tag_set' - -# mixed in to some of the Flapjack data classes - -module Flapjack - - module Tagged - - def tag_prefix - self.class.name.split('::').last.downcase + '_tag' - end - - # return the set of tags for this object - def tags - @tags ||= Flapjack::Data::TagSet.new( @redis.keys("#{tag_prefix}:*").inject([]) {|memo, tag| - if Flapjack::Data::Tag.find(tag, :redis => @redis).include?(@id.to_s) - memo << tag.sub(/^#{tag_prefix}:/, '') - end - memo - } ) - end - - # adds tags to this object - def add_tags(*enum) - enum.each do |t| - Flapjack::Data::Tag.create("#{tag_prefix}:#{t}", [@id], :redis => @redis) - tags.add(t) - end - end - - # removes tags from this object - def delete_tags(*enum) - enum.each do |t| - tag = Flapjack::Data::Tag.find("#{tag_prefix}:#{t}", :redis => @redis) - tag.delete(@id) - tags.delete(t) - end - end - - end - -end \ No newline at end of file diff --git a/spec/lib/flapjack/data/contact_spec.rb b/spec/lib/flapjack/data/contact_spec.rb index 273488f7f..a17db067b 100644 --- a/spec/lib/flapjack/data/contact_spec.rb +++ b/spec/lib/flapjack/data/contact_spec.rb @@ -1,11 +1,6 @@ require 'spec_helper' -require 'active_support/time_with_zone' -require 'ice_cube' require 'flapjack/data/contact' -require 'flapjack/data/entity_check' -require 'flapjack/data/notification_rule' -require 'flapjack/data/tag_set' describe Flapjack::Data::Contact, :redis => true do @@ -24,7 +19,7 @@ let(:general_notification_rule_data) { {:entities => [], - :tags => Flapjack::Data::TagSet.new([]), + :tags => Set.new([]), :time_restrictions => [], :unknown_media => [], :warning_media => ['email', 'sms', 'sms_twilio', 'jabber', 'pagerduty', 'sns'], @@ -193,9 +188,8 @@ expect(rules.select {|r| r.is_specific? }.size).to eq(1) end - it "deletes a contact by id, including linked entities, checks, tags and notification rules" do + it "deletes a contact by id, including linked entities, checks and notification rules" do contact = Flapjack::Data::Contact.find_by_id('c362', :redis => @redis) - contact.add_tags('admin') entity_name = 'abc-123' @@ -206,10 +200,8 @@ expect { expect { - expect { - contact.delete! - }.to change { Flapjack::Data::Contact.all(:redis => @redis).size }.by(-1) - }.to change { @redis.smembers('contact_tag:admin').size }.by(-1) + contact.delete! + }.to change { Flapjack::Data::Contact.all(:redis => @redis).size }.by(-1) }.to change { entity.contacts.size }.by(-1) end diff --git a/spec/lib/flapjack/data/entity_check_spec.rb b/spec/lib/flapjack/data/entity_check_spec.rb index 4f6307801..be484808a 100644 --- a/spec/lib/flapjack/data/entity_check_spec.rb +++ b/spec/lib/flapjack/data/entity_check_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -require 'flapjack/data/entity' require 'flapjack/data/entity_check' -require 'flapjack/data/tag_set' describe Flapjack::Data::EntityCheck, :redis => true do @@ -1404,7 +1402,7 @@ def time_before(t, min, sec = 0) ec = Flapjack::Data::EntityCheck.for_entity_name('foo-app-01.example.com', 'Disk / Utilisation', :create_entity => true, :redis => @redis) tags = ec.tags expect(tags).not_to be_nil - expect(tags).to be_a(Flapjack::Data::TagSet) + expect(tags).to be_a(Set) expect(['foo-app-01', 'example.com', 'disk', '/', 'utilisation'].to_set.subset?(tags)).to be true end diff --git a/spec/lib/flapjack/data/event_spec.rb b/spec/lib/flapjack/data/event_spec.rb index 29d6b6d01..38ad82f83 100644 --- a/spec/lib/flapjack/data/event_spec.rb +++ b/spec/lib/flapjack/data/event_spec.rb @@ -302,7 +302,7 @@ expect(event.time).to eq(event_data['time']) expect(event.id).to eq('xyz-example.com:ping') expect(event.type).to eq('service') - expect(event.tags).to be_an_instance_of(Flapjack::Data::TagSet) + expect(event.tags).to be_an_instance_of(Set) expect(event.tags).to include('dev') expect(event.tags).to_not include('prod') diff --git a/spec/lib/flapjack/data/tag_spec.rb b/spec/lib/flapjack/data/tag_spec.rb deleted file mode 100644 index f16a53e85..000000000 --- a/spec/lib/flapjack/data/tag_spec.rb +++ /dev/null @@ -1,36 +0,0 @@ -require 'spec_helper' -require 'flapjack/data/tag' - -describe Flapjack::Data::Tag, :redis => true do - - it "adds references to tags" do - tags = Flapjack::Data::Tag.create('special', ['apple', 'button', 'carbon'], :redis => @redis) - - expect(tags).to include('carbon') - expect(tags).not_to include('chocolate') - - tags.add('chocolate') - expect(tags).to include('chocolate') - end - - it "deletes references from tags" do - tags = Flapjack::Data::Tag.create('special', ['apple', 'button', 'carbon'], :redis => @redis) - - expect(tags).to include('apple') - expect(tags).to include('button') - - tags.delete('button') - expect(tags).to include('apple') - expect(tags).not_to include('button') - end - - it "lists references contained in a tag" do - t1 = Flapjack::Data::Tag.create('special', ['apple', 'button', 'carbon'], :redis => @redis) - - t2 = Flapjack::Data::Tag.find('special', :redis => @redis) - expect(t2).to include('apple') - expect(t2).to include('carbon') - expect(t2).not_to include('chocolate') - end - -end From 6548a04194a80906d4fab677caed904578ae9f6d Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Tue, 23 Sep 2014 10:44:54 +0930 Subject: [PATCH 08/69] fix 1.9 Gemfile post merge --- .ruby-version | 2 +- Gemfile-ruby1.9.lock | 19 +++++++++++++++++++ Gemfile.lock | 28 ++++++++++++++-------------- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/.ruby-version b/.ruby-version index eca07e4c1..ac2cdeba0 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.1.2 +2.1.3 diff --git a/Gemfile-ruby1.9.lock b/Gemfile-ruby1.9.lock index 4acca7b2d..a4c62171f 100644 --- a/Gemfile-ruby1.9.lock +++ b/Gemfile-ruby1.9.lock @@ -36,6 +36,7 @@ GEM multi_json (~> 1.0) addressable (2.3.6) async_rack_test (0.0.5) + awesome_print (1.2.0) blather (0.8.8) activesupport (>= 2.3.11) eventmachine (>= 1.0.0) @@ -84,6 +85,7 @@ GEM eventmachine (>= 1.0.0.beta.1) eventmachine (1.0.3) ffi (1.9.3) + find_a_port (1.0.1) formatador (0.2.5) fuubar (2.0.0) rspec (~> 3.0) @@ -111,6 +113,7 @@ GEM http_parser.rb (0.6.0) i18n (0.6.11) ice_cube (0.12.1) + json (1.8.1) listen (2.7.9) celluloid (>= 0.15.2) rb-fsevent (>= 0.9.3) @@ -130,6 +133,16 @@ GEM mini_portile (= 0.6.0) numerizer (0.1.1) oj (2.10.2) + pact (1.3.3) + awesome_print (~> 1.1) + find_a_port (~> 1.0.1) + json + rack-test (~> 0.6.2) + randexp (~> 0.1.7) + rspec (>= 2.14) + term-ansicolor (~> 1.0) + thor + webrick perftools.rb (2.0.1) pry (0.10.1) coderay (~> 1.1.0) @@ -142,6 +155,7 @@ GEM rack-test (0.6.2) rack (>= 1.0) rake (10.3.2) + randexp (0.1.7) rb-fsevent (0.9.4) rb-inotify (0.9.5) ffi (>= 0.5.0) @@ -190,6 +204,8 @@ GEM rack-protection (~> 1.4) tilt (~> 1.3, >= 1.3.4) slop (3.6.0) + term-ansicolor (1.3.0) + tins (~> 1.0) terminal-table (1.4.5) thin (1.6.2) daemons (>= 1.0.9) @@ -199,6 +215,7 @@ GEM tilt (1.4.1) timers (4.0.1) hitimes + tins (1.3.3) trollop (2.0) tzinfo (1.0.1) tzinfo-data (1.2014.7) @@ -208,6 +225,7 @@ GEM webmock (1.18.0) addressable (>= 2.3.6) crack (>= 0.3.2) + webrick (1.3.1) PLATFORMS ruby @@ -222,6 +240,7 @@ DEPENDENCIES guard guard-cucumber guard-rspec + pact perftools.rb rack-test rb-fsevent diff --git a/Gemfile.lock b/Gemfile.lock index 50f5475ba..66ac2ab59 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -131,7 +131,7 @@ GEM mini_portile (= 0.6.0) numerizer (0.1.1) oj (2.10.1) - pact (1.3.2) + pact (1.3.3) awesome_print (~> 1.1) find_a_port (~> 1.0.1) json @@ -173,18 +173,18 @@ GEM rspec-core (>= 2.5.0) rspec-expectations (>= 2.5.0) rspec-mocks (>= 2.5.0) - rspec (3.0.0) - rspec-core (~> 3.0.0) - rspec-expectations (~> 3.0.0) - rspec-mocks (~> 3.0.0) - rspec-core (3.0.4) - rspec-support (~> 3.0.0) - rspec-expectations (3.0.4) + rspec (3.1.0) + rspec-core (~> 3.1.0) + rspec-expectations (~> 3.1.0) + rspec-mocks (~> 3.1.0) + rspec-core (3.1.4) + rspec-support (~> 3.1.0) + rspec-expectations (3.1.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.0.0) - rspec-mocks (3.0.4) - rspec-support (~> 3.0.0) - rspec-support (3.0.4) + rspec-support (~> 3.1.0) + rspec-mocks (3.1.1) + rspec-support (~> 3.1.0) + rspec-support (3.1.0) rubinius-actor (0.0.2) rubinius-core-api rubinius-core-api (0.0.1) @@ -208,10 +208,10 @@ GEM daemons (>= 1.0.9) eventmachine (>= 1.0.0) rack (>= 1.0.0) - thor (0.18.1) + thor (0.19.1) tilt (1.4.1) timers (1.1.0) - tins (1.3.2) + tins (1.3.3) trollop (2.0) tzinfo (1.0.1) tzinfo-data (1.2014.6) From aaddff1fe43f1d6229549d39eb24cbe2a20dc070 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Tue, 23 Sep 2014 12:55:36 +0930 Subject: [PATCH 09/69] contact pacts passing --- lib/flapjack/data/contact.rb | 4 +- lib/flapjack/gateways/jsonapi.rb | 9 +- .../gateways/jsonapi/contact_methods.rb | 2 +- .../pacts/flapjack-diner_v1.0.json | 422 ++++++++++++++++-- .../provider_states_for_flapjack-diner.rb | 69 ++- 5 files changed, 456 insertions(+), 50 deletions(-) diff --git a/lib/flapjack/data/contact.rb b/lib/flapjack/data/contact.rb index a17981a08..5c5280a7a 100644 --- a/lib/flapjack/data/contact.rb +++ b/lib/flapjack/data/contact.rb @@ -480,7 +480,7 @@ def to_json(*args) "media_intervals" => self.media_intervals, "media_rollup_thresholds" => self.media_rollup_thresholds, "timezone" => self.timezone.name, - "tags" => self.tags.to_a + "tags" => self.tags.to_a.sort }.to_json end @@ -490,7 +490,7 @@ def to_jsonapi(opts = {}) "last_name" => self.last_name, "email" => self.email, "timezone" => self.timezone.name, - "tags" => self.tags.to_a, + "tags" => self.tags.to_a.sort, "links" => { :entities => opts[:entity_ids] || [], :media => self.media_ids || [], diff --git a/lib/flapjack/gateways/jsonapi.rb b/lib/flapjack/gateways/jsonapi.rb index 81f4cca93..aa72dbb83 100644 --- a/lib/flapjack/gateways/jsonapi.rb +++ b/lib/flapjack/gateways/jsonapi.rb @@ -136,7 +136,14 @@ def initialize(resource) "#{request_info[:path_info]}#{query_string}") end - [status, {}, response_body] + headers = if 'DELETE'.eql?(request_info[:request_method]) + # not set by default for delete, but the error structure is JSON + {'Content-Type' => JSONAPI_MEDIA_TYPE} + else + {} + end + + [status, headers, response_body] } request_info = { diff --git a/lib/flapjack/gateways/jsonapi/contact_methods.rb b/lib/flapjack/gateways/jsonapi/contact_methods.rb index 0dbfcee6a..99235f60b 100644 --- a/lib/flapjack/gateways/jsonapi/contact_methods.rb +++ b/lib/flapjack/gateways/jsonapi/contact_methods.rb @@ -45,7 +45,7 @@ def bulk_contact_operation(contact_ids, &block) missing_ids = contacts_by_id.select {|k, v| v.nil? }.keys unless missing_ids.empty? semaphore.release - halt(404, "Contacts with ids #{missing_ids.join(', ')} were not found") + raise Flapjack::Gateways::JSONAPI::ContactsNotFound.new(missing_ids) end block.call(contacts_by_id.select {|k, v| !v.nil? }.values) diff --git a/spec/service_consumers/pacts/flapjack-diner_v1.0.json b/spec/service_consumers/pacts/flapjack-diner_v1.0.json index af2a2e65f..432e7ec7f 100644 --- a/spec/service_consumers/pacts/flapjack-diner_v1.0.json +++ b/spec/service_consumers/pacts/flapjack-diner_v1.0.json @@ -7,11 +7,104 @@ }, "interactions": [ { - "description": "a GET request for check 'www.example.com:SSH'", + "description": "a POST request with one check", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/checks", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "checks": [ + { + "name": "PING", + "entity_id": "1234" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:PING" + ] + } + }, + { + "description": "a POST request with two checks", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/checks", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "checks": [ + { + "name": "SSH", + "entity_id": "1234" + }, + { + "name": "PING", + "entity_id": "1234" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:SSH", + "www.example.com:PING" + ] + } + }, + { + "description": "a PATCH request for a single check", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "patch", + "path": "/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/checks/0/enabled", + "value": false + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for a single check", "provider_state": "no entity exists", "request": { - "method": "get", - "path": "/checks/www.example.com:SSH" + "method": "patch", + "path": "/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/checks/0/enabled", + "value": false + } + ] }, "response": { "status": 404, @@ -20,17 +113,36 @@ }, "body": { "errors": [ - "could not find entity checks: 'www.example.com:SSH'" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a GET request for check 'www.example.com:SSH'", + "description": "a GET request for all checks", + "provider_state": "no entity exists", + "request": { + "method": "get", + "path": "/checks" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "checks": [ + + ] + } + } + }, + { + "description": "a GET request for all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/checks/www.example.com:SSH" + "path": "/checks" }, "response": { "status": 200, @@ -54,11 +166,11 @@ } }, { - "description": "a GET request for all checks", + "description": "a GET request for check 'www.example.com:SSH'", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/checks" + "path": "/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -82,38 +194,38 @@ } }, { - "description": "a GET request for all checks", + "description": "a GET request for check 'www.example.com:SSH'", "provider_state": "no entity exists", "request": { "method": "get", - "path": "/checks" + "path": "/checks/www.example.com:SSH" }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ - + "errors": [ + "could not find entity checks: 'www.example.com:SSH'" ] } } }, { - "description": "a PATCH request for a single check", - "provider_state": "no entity exists", + "description": "a PATCH request to change properties for a single contact", + "provider_state": "no contact exists", "request": { "method": "patch", - "path": "/checks/www.example.com:SSH", + "path": "/contacts/323", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/checks/0/enabled", - "value": false + "path": "/contacts/0/timezone", + "value": "UTC" } ] }, @@ -124,25 +236,47 @@ }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find contacts '323'" ] } } }, { - "description": "a PATCH request for a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request to change links for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { "method": "patch", - "path": "/checks/www.example.com:SSH", + "path": "/contacts/abc,872", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request to change properties for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "patch", + "path": "/contacts/abc", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/checks/0/enabled", - "value": false + "path": "/contacts/0/timezone", + "value": "UTC" } ] }, @@ -152,23 +286,70 @@ } }, { - "description": "a POST request with two checks", - "provider_state": "an entity 'www.example.com' exists", + "description": "a PATCH requestto change a link for a single contact", + "provider_state": "a contact with id '872' exists", + "request": { + "method": "patch", + "path": "/contacts/872", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request to change properties for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", + "request": { + "method": "patch", + "path": "/contacts/abc,872", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one contact", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/checks", + "path": "/contacts", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ - { - "name": "SSH", - "entity_id": "1234" - }, + "contacts": [ { - "name": "PING", - "entity_id": "1234" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] } ] } @@ -179,25 +360,37 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "www.example.com:SSH", - "www.example.com:PING" + "abc" ] } }, { - "description": "a POST request with one check", - "provider_state": "an entity 'www.example.com' exists", + "description": "a POST request with two contacts", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/checks", + "path": "/contacts", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "contacts": [ { - "name": "PING", - "entity_id": "1234" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + }, + { + "id": "def", + "first_name": "Joan", + "last_name": "Smith", + "email": "joans@example.com" } ] } @@ -208,9 +401,152 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "www.example.com:PING" + "abc", + "def" ] } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts 'abc'" + ] + } + } + }, + { + "description": "a DELETE request for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", + "request": { + "method": "delete", + "path": "/contacts/abc,872", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a GET request for all contacts", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "get", + "path": "/contacts" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + } + ] + } + } + }, + { + "description": "a GET request for all contacts", + "provider_state": "no contact exists", + "request": { + "method": "get", + "path": "/contacts" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "contacts": [ + + ] + } + } + }, + { + "description": "a GET request for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "get", + "path": "/contacts/abc" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + } + ] + } + } + }, + { + "description": "a GET request for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "get", + "path": "/contacts/abc" + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts 'abc'" + ] + } + } } ], "metadata": { diff --git a/spec/service_consumers/provider_states_for_flapjack-diner.rb b/spec/service_consumers/provider_states_for_flapjack-diner.rb index a7c670ce6..b8d11d275 100644 --- a/spec/service_consumers/provider_states_for_flapjack-diner.rb +++ b/spec/service_consumers/provider_states_for_flapjack-diner.rb @@ -1,9 +1,14 @@ Pact.provider_states_for "flapjack-diner" do - provider_state "no entity exists" do - set_up do + provider_state "no contact exists" do + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb end + end + provider_state "no entity exists" do tear_down do Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') @@ -11,7 +16,7 @@ end end - provider_state "an entity 'www.example.com' exists" do + provider_state "an entity 'www.example.com' with id '1234' exists" do set_up do redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') @@ -43,4 +48,62 @@ end end + provider_state "a contact with id 'abc' exists" do + set_up do + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + contact_data = {'id' => 'abc', + 'first_name' => 'Jim', + 'last_name' => 'Smith', + 'email' => 'jims@example.com', + 'timezone' => 'UTC', + 'tags' => ['admin', 'night_shift']} + Flapjack::Data::Contact.add(contact_data, :redis => redis) + end + + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end + + provider_state "a contact with id '872' exists" do + set_up do + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + contact_data = {'id' => '872', 'first_name' => 'John', + 'last_name' => 'Smith', 'email' => 'jsmith@example.com'} + Flapjack::Data::Contact.add(contact_data, :redis => redis) + end + + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end + + provider_state "contacts with ids 'abc' and '872' exist" do + set_up do + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + contact_data = {'id' => 'abc', + 'first_name' => 'Jim', + 'last_name' => 'Smith', + 'email' => 'jims@example.com', + 'timezone' => 'UTC', + 'tags' => ['admin', 'night_shift']} + Flapjack::Data::Contact.add(contact_data, :redis => redis) + contact_data_2 = {'id' => '872', + 'first_name' => 'John', + 'last_name' => 'Smith', + 'email' => 'jsmith@example.com'} + Flapjack::Data::Contact.add(contact_data_2, :redis => redis) + end + + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end + end \ No newline at end of file From 6d1f82295dc9b68b3b45f5b61fa9b8511619fea2 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Tue, 23 Sep 2014 13:54:59 +0930 Subject: [PATCH 10/69] update oj, multi_json --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8cfc335b1..7e1a29d25 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -120,14 +120,14 @@ GEM mime-types (2.3) mini_portile (0.6.0) msgpack (0.5.8) - multi_json (1.8.2) + multi_json (1.10.1) multi_test (0.0.3) niceogiri (1.1.2) nokogiri (~> 1.5) nokogiri (1.6.2.1) mini_portile (= 0.6.0) numerizer (0.1.1) - oj (2.10.1) + oj (2.10.2) pry (0.9.12.4) coderay (~> 1.0) method_source (~> 0.8) From ff90b9ee8ef02070af2a5dd2fc9c118bdf6641a0 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Tue, 23 Sep 2014 15:30:34 +0930 Subject: [PATCH 11/69] json/oj cleanup, see #656 --- features/steps/events_steps.rb | 4 +- .../steps/flapjack-netsaint-parser_steps.rb | 2 +- features/support/env.rb | 7 +-- lib/flapjack.rb | 10 ++++ lib/flapjack/cli/import.rb | 7 +-- lib/flapjack/cli/purge.rb | 8 +-- lib/flapjack/cli/receiver.rb | 3 -- lib/flapjack/cli/server.rb | 5 -- lib/flapjack/data/contact.rb | 31 ++++++----- lib/flapjack/data/entity.rb | 17 +++--- lib/flapjack/data/entity_check.rb | 7 ++- lib/flapjack/data/event.rb | 7 +-- lib/flapjack/data/notification.rb | 16 +++--- lib/flapjack/data/notification_rule.rb | 54 +++++++++---------- lib/flapjack/data/tag.rb | 4 -- lib/flapjack/data/tag_set.rb | 4 -- lib/flapjack/gateways/jabber.rb | 5 +- lib/flapjack/gateways/jsonapi.rb | 4 +- .../gateways/jsonapi/check_methods.rb | 2 +- .../gateways/jsonapi/contact_methods.rb | 2 +- .../gateways/jsonapi/entity_methods.rb | 2 +- .../gateways/jsonapi/medium_methods.rb | 4 +- .../gateways/jsonapi/metrics_methods.rb | 2 +- .../jsonapi/notification_rule_methods.rb | 2 +- .../jsonapi/pagerduty_credential_methods.rb | 4 +- .../jsonapi/rack/json_params_parser.rb | 2 +- .../gateways/jsonapi/report_methods.rb | 6 +-- lib/flapjack/gateways/oobetet.rb | 5 +- lib/flapjack/gateways/pagerduty.rb | 12 ++--- lib/flapjack/gateways/web.rb | 5 +- lib/flapjack/notifier.rb | 6 +-- lib/flapjack/processor.rb | 2 +- .../flapjack/data/notification_rule_spec.rb | 6 ++- spec/spec_helper.rb | 6 --- spec/support/jsonapi_helper.rb | 2 +- tasks/benchmarks.rake | 5 +- tasks/profile.rake | 2 +- tmp/acknowledge.rb | 3 -- tmp/create_event_ok.rb | 3 -- tmp/create_event_unknown.rb | 3 -- tmp/create_events_failure.rb | 3 -- tmp/create_events_ok.rb | 3 -- tmp/create_events_ok_fail_ack_ok.rb | 3 -- tmp/create_events_ok_failure.rb | 7 +-- tmp/create_events_ok_failure_ack.rb | 3 -- tmp/test_json_post.rb | 7 +-- tmp/test_notification_rules_api.rb | 5 +- 47 files changed, 132 insertions(+), 180 deletions(-) diff --git a/features/steps/events_steps.rb b/features/steps/events_steps.rb index 08488648c..3764b4c45 100644 --- a/features/steps/events_steps.rb +++ b/features/steps/events_steps.rb @@ -19,7 +19,7 @@ def drain_notifications end def submit_event(event) - @redis.rpush 'events', event.to_json + @redis.rpush('events', Flapjack.dump_json(event)) end def set_scheduled_maintenance(entity, check, duration) @@ -300,7 +300,7 @@ def icecube_schedule_to_time_restriction(sched, time_zone) puts "There #{(rule_ids.length == 1) ? 'is' : 'are'} #{rule_ids.length} notification rule#{(rule_ids.length == 1) ? '' : 's'} for user #{contact}:" rule_ids.each {|rule_id| rule = Flapjack::Data::NotificationRule.find_by_id(rule_id, :redis => @redis) - puts rule.to_json + puts Flapjack.dump_json(rule) } end diff --git a/features/steps/flapjack-netsaint-parser_steps.rb b/features/steps/flapjack-netsaint-parser_steps.rb index 6e1e059dd..6dd1ec984 100644 --- a/features/steps/flapjack-netsaint-parser_steps.rb +++ b/features/steps/flapjack-netsaint-parser_steps.rb @@ -14,7 +14,7 @@ Then /^I should see a valid JSON output$/ do expect { - @data = Oj.load(@output) + @data = Flapjack.load_json(@output) }.not_to raise_error end diff --git a/features/support/env.rb b/features/support/env.rb index 2b1f6ff70..b60b97958 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -15,7 +15,6 @@ add_filter '/features/' end SimpleCov.at_exit do - Oj.default_options = { :mode => :compat } SimpleCov.result.format! end end @@ -34,11 +33,7 @@ require 'webmock/cucumber' WebMock.disable_net_connect! -require 'oj' -Oj.mimic_JSON -Oj.default_options = { :indent => 0, :mode => :strict } -require 'active_support/json' - +require 'flapjack' require 'flapjack/notifier' require 'flapjack/processor' require 'flapjack/patches' diff --git a/lib/flapjack.rb b/lib/flapjack.rb index 48e535b9d..608a1f56c 100644 --- a/lib/flapjack.rb +++ b/lib/flapjack.rb @@ -1,6 +1,16 @@ #!/usr/bin/env ruby +require 'oj' + module Flapjack + def self.load_json(data) + Oj.load(data, :mode => :strict, :symbol_keys => false) + end + + def self.dump_json(data) + Oj.dump(data, :mode => :compat, :time_format => :ruby, :indent => 0) + end + end diff --git a/lib/flapjack/cli/import.rb b/lib/flapjack/cli/import.rb index 149d9e509..d1595ac5c 100644 --- a/lib/flapjack/cli/import.rb +++ b/lib/flapjack/cli/import.rb @@ -1,8 +1,5 @@ #!/usr/bin/env ruby -require 'oj' -Oj.default_options = { :indent => 0, :mode => :strict } - require 'redis' require 'flapjack/configuration' @@ -32,7 +29,7 @@ def initialize(global_options, options) # {'contacts' => [CONTACT_HASH, ...]} def contacts - conts = Oj.load(File.new(@options[:from])) + conts = Flapjack.load_json(File.new(@options[:from])) if conts && conts.is_a?(Enumerable) && conts.any? {|e| !e['id'].nil?} conts.each do |contact| @@ -47,7 +44,7 @@ def contacts end def entities - ents = Oj.load(File.new(@options[:from])) + ents = Flapjack.load_json(File.new(@options[:from])) if ents && ents.is_a?(Enumerable) && ents.any? {|e| !e['id'].nil?} ents.each do |entity| diff --git a/lib/flapjack/cli/purge.rb b/lib/flapjack/cli/purge.rb index 9809f24e4..b09a11943 100644 --- a/lib/flapjack/cli/purge.rb +++ b/lib/flapjack/cli/purge.rb @@ -35,10 +35,10 @@ def check_history else Flapjack::Data::EntityCheck.all(:redis => redis, :create_entity => true) end - purged = checks.map do |check| - p = check.purge_history(options) - p == 0 ? nil : p - end.compact + purged = checks.inject([]) do |memo, check| + pu = check.purge_history(options) + memo << pu unless pu == 0 + end if purged.empty? puts "Nothing to do" diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index 0e868ba28..11ab7c5cc 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -3,9 +3,6 @@ require 'dante' require 'redis' -require 'oj' -Oj.default_options = { :indent => 0, :mode => :strict } - require 'flapjack/configuration' require 'flapjack/data/event' require 'flapjack/patches' diff --git a/lib/flapjack/cli/server.rb b/lib/flapjack/cli/server.rb index dc652596c..3a668f21a 100644 --- a/lib/flapjack/cli/server.rb +++ b/lib/flapjack/cli/server.rb @@ -2,11 +2,6 @@ require 'dante' -require 'oj' -Oj.mimic_JSON -Oj.default_options = { :indent => 0, :mode => :strict } -require 'active_support/json' - require 'flapjack/coordinator' module Flapjack diff --git a/lib/flapjack/data/contact.rb b/lib/flapjack/data/contact.rb index a17981a08..f0bd7679b 100644 --- a/lib/flapjack/data/contact.rb +++ b/lib/flapjack/data/contact.rb @@ -471,21 +471,23 @@ def timezone=(tz) end end - def to_json(*args) - { "id" => self.id, - "first_name" => self.first_name, - "last_name" => self.last_name, - "email" => self.email, - "media" => self.media, - "media_intervals" => self.media_intervals, - "media_rollup_thresholds" => self.media_rollup_thresholds, - "timezone" => self.timezone.name, - "tags" => self.tags.to_a - }.to_json - end + # def to_json + # {"id" => self.id, + # "first_name" => self.first_name, + # "last_name" => self.last_name, + # "email" => self.email, + # "media" => self.media, + # "media_intervals" => self.media_intervals, + # "media_rollup_thresholds" => self.media_rollup_thresholds, + # "timezone" => self.timezone.name, + # "tags" => self.tags.to_a + # } + # Flapjack.dump_json(json_data) + # end def to_jsonapi(opts = {}) - { "id" => self.id, + json_data = { + "id" => self.id, "first_name" => self.first_name, "last_name" => self.last_name, "email" => self.email, @@ -496,7 +498,8 @@ def to_jsonapi(opts = {}) :media => self.media_ids || [], :notification_rules => self.notification_rule_ids || [], } - }.to_json + } + Flapjack.dump_json(json_data) end private diff --git a/lib/flapjack/data/entity.rb b/lib/flapjack/data/entity.rb index dacd9fd29..51fdbaf69 100644 --- a/lib/flapjack/data/entity.rb +++ b/lib/flapjack/data/entity.rb @@ -581,22 +581,23 @@ def check_count checks.length end - def as_json(*args) - { - "id" => self.id, - "name" => self.name, - } - end + # def as_json(*args) + # { + # "id" => self.id, + # "name" => self.name, + # } + # end def to_jsonapi(opts = {}) - { + json_data = { "id" => self.id, "name" => self.name, "links" => { :contacts => opts[:contact_ids] || [], :checks => opts[:check_ids] || [], } - }.to_json + } + Flapjack.dump_json(json_data) end private diff --git a/lib/flapjack/data/entity_check.rb b/lib/flapjack/data/entity_check.rb index 61cb44cf2..d025c6e85 100755 --- a/lib/flapjack/data/entity_check.rb +++ b/lib/flapjack/data/entity_check.rb @@ -1,7 +1,5 @@ #!/usr/bin/env ruby -require 'oj' - require 'flapjack/patches' require 'flapjack/data/contact' @@ -995,7 +993,7 @@ def self.enabled_for(check_ids, opts = {}) end def to_jsonapi(opts = {}) - { + json_data = { "id" => @key, "name" => @check, "entity_name" => @entity.name, @@ -1003,7 +1001,8 @@ def to_jsonapi(opts = {}) "links" => { :entities => opts[:entity_ids] || [], } - }.to_json + } + Flapjack.dump_json(json_data) end private diff --git a/lib/flapjack/data/event.rb b/lib/flapjack/data/event.rb index df3999230..47c5bd60e 100755 --- a/lib/flapjack/data/event.rb +++ b/lib/flapjack/data/event.rb @@ -1,6 +1,7 @@ #!/usr/bin/env ruby -require 'oj' +require 'flapjack' + require 'flapjack/data/tag_set' module Flapjack @@ -120,7 +121,7 @@ def self.next(queue, opts = {}) def self.parse_and_validate(raw, opts = {}) errors = [] - if parsed = ::Oj.load(raw) + if parsed = ::Flapjack.load_json(raw) if parsed.is_a?(Hash) errors = validation_errors_for_hash(parsed, opts) else @@ -177,7 +178,7 @@ def self.add(evt, opts = {}) raise "Redis connection not set" unless redis = opts[:redis] evt['time'] = Time.now.to_i if evt['time'].nil? - redis.lpush('events', ::Oj.dump(evt)) + redis.lpush('events', ::Flapjack.dump_json(evt)) end # Provide a count of the number of events on the queue to be processed. diff --git a/lib/flapjack/data/notification.rb b/lib/flapjack/data/notification.rb index 152444a90..6f59fe04c 100644 --- a/lib/flapjack/data/notification.rb +++ b/lib/flapjack/data/notification.rb @@ -1,7 +1,5 @@ #!/usr/bin/env ruby -require 'oj' - require 'flapjack/data/contact' require 'flapjack/data/event' require 'flapjack/data/message' @@ -66,7 +64,7 @@ def self.add(queue, event, opts = {}) 'severity' => opts[:severity], 'tags' => tag_data } - redis.rpush(queue, Oj.dump(notif)) + redis.rpush(queue, Flapjack.dump_json(notif)) end def self.next(queue, opts = {}) @@ -82,7 +80,7 @@ def self.next(queue, opts = {}) return unless raw end begin - parsed = ::Oj.load( raw ) + parsed = ::Flapjack.load_json( raw ) rescue Oj::Error => e if options[:logger] options[:logger].warn("Error deserialising notification json: #{e}, raw json: #{raw.inspect}") @@ -133,7 +131,7 @@ def messages(contacts, opts = {}) media = contact.media logger.debug "Notification#messages: creating messages for contact: #{contact_id} " + - "event_id: \"#{@event_id}\" state: #{@state} event_tags: #{@tags.to_json} media: #{media.inspect}" + "event_id: \"#{@event_id}\" state: #{@state} event_tags: #{Flapjack.dump_json(@tags)} media: #{media.inspect}" rlen = rules.length logger.debug "found #{rlen} rule#{(rlen == 1) ? '' : 's'} for contact #{contact_id}" @@ -144,7 +142,7 @@ def messages(contacts, opts = {}) # for time, entity and tags matchers = rules.select do |rule| logger.debug("considering rule with entities: #{rule.entities}, entities regex: #{rule.regex_entities}, - tags: #{rule.tags.to_json} and regex tags: #{rule.regex_tags.to_json}") + tags: #{Flapjack.dump_json(rule.tags)} and regex tags: #{Flapjack.dump_json(rule.regex_tags)}") rule_has_tags = rule.tags ? (rule.tags.length > 0) : false rule_has_regex_tags = rule.regex_tags ? (rule.regex_tags.length > 0) : false rule_has_entities = rule.entities ? (rule.entities.length > 0) : false @@ -162,7 +160,7 @@ def messages(contacts, opts = {}) logger.debug "#{matchers.length} matchers remain for this contact after time, entity and tags are matched:" matchers.each do |matcher| - logger.debug " - #{matcher.to_json}" + logger.debug " - #{matcher.to_jsonapi}" end # delete any general matchers if there are more specific matchers left @@ -175,7 +173,7 @@ def messages(contacts, opts = {}) if num_matchers != matchers.length logger.debug("removal of general matchers when entity specific matchers are present: number of matchers changed from #{num_matchers} to #{matchers.length} for contact id: #{contact_id}") matchers.each do |matcher| - logger.debug " - #{matcher.to_json}" + logger.debug " - #{matcher.to_jsonapi}" end end end @@ -185,7 +183,7 @@ def messages(contacts, opts = {}) if blackhole_matchers.length > 0 logger.debug "dropping this media as #{blackhole_matchers.length} blackhole matchers are present:" blackhole_matchers.each {|bm| - logger.debug " - #{bm.to_json}" + logger.debug " - #{bm.to_jsonapi}" } next else diff --git a/lib/flapjack/data/notification_rule.rb b/lib/flapjack/data/notification_rule.rb index 25eab36f1..3b4904937 100644 --- a/lib/flapjack/data/notification_rule.rb +++ b/lib/flapjack/data/notification_rule.rb @@ -1,6 +1,5 @@ #!/usr/bin/env ruby -require 'oj' require 'active_support/time' require 'ice_cube' require 'flapjack/utility' @@ -108,20 +107,19 @@ def self.time_restriction_to_icecube_schedule(tr, timezone, opts = {}) nil end - def to_json(*args) - self.class.hashify(:id, :contact_id, :tags, :regex_tags, :entities, :regex_entities, - :time_restrictions, :unknown_media, :warning_media, :critical_media, - :unknown_blackhole, :warning_blackhole, :critical_blackhole) {|k| - [k, self.send(k)] - }.to_json - end - def to_jsonapi(opts = {}) - self.class.hashify(:id, :tags, :regex_tags, :entities, :regex_entities, + json_data = self.class.hashify(:id, :tags, :regex_tags, :entities, :regex_entities, :time_restrictions, :unknown_media, :warning_media, :critical_media, :unknown_blackhole, :warning_blackhole, :critical_blackhole) {|k| - [k, self.send(k)] - }.merge(:links => {:contacts => [self.contact_id]}).to_json + case k + when :tags, :regex_tags + [k.to_s, self.send(k).to_a.sort] + else + [k.to_s, self.send(k)] + end + }.merge('links' => {'contacts' => [self.contact_id]}) + + Flapjack.dump_json(json_data) end # entity names match? @@ -227,14 +225,14 @@ def self.add_or_update(rule_data, options = {}) json_rule_data = { :id => rule_data[:id].to_s, :contact_id => rule_data[:contact_id].to_s, - :entities => Oj.dump(rule_data[:entities]), - :regex_entities => Oj.dump(rule_data[:regex_entities]), - :tags => Oj.dump(tag_data), - :regex_tags => Oj.dump(regex_tag_data), - :time_restrictions => Oj.dump(rule_data[:time_restrictions], :mode => :compat), - :unknown_media => Oj.dump(rule_data[:unknown_media]), - :warning_media => Oj.dump(rule_data[:warning_media]), - :critical_media => Oj.dump(rule_data[:critical_media]), + :entities => Flapjack.dump_json(rule_data[:entities]), + :regex_entities => Flapjack.dump_json(rule_data[:regex_entities]), + :tags => Flapjack.dump_json(tag_data), + :regex_tags => Flapjack.dump_json(regex_tag_data), + :time_restrictions => Flapjack.dump_json(rule_data[:time_restrictions]), + :unknown_media => Flapjack.dump_json(rule_data[:unknown_media]), + :warning_media => Flapjack.dump_json(rule_data[:warning_media]), + :critical_media => Flapjack.dump_json(rule_data[:critical_media]), :unknown_blackhole => rule_data[:unknown_blackhole], :warning_blackhole => rule_data[:warning_blackhole], :critical_blackhole => rule_data[:critical_blackhole], @@ -400,16 +398,16 @@ def refresh rule_data = @redis.hgetall("notification_rule:#{@id}") @contact_id = rule_data['contact_id'] - tags = Oj.load(rule_data['tags'] || '') + tags = Flapjack.load_json(rule_data['tags'] || '') @tags = tags ? Flapjack::Data::TagSet.new(tags) : nil - regex_tags = Oj.load(rule_data['regex_tags'] || '') + regex_tags = Flapjack.load_json(rule_data['regex_tags'] || '') @regex_tags = regex_tags ? Flapjack::Data::TagSet.new(regex_tags) : nil - @entities = Oj.load(rule_data['entities'] || '') - @regex_entities = Oj.load(rule_data['regex_entities'] || '') - @time_restrictions = Oj.load(rule_data['time_restrictions'] || '') - @unknown_media = Oj.load(rule_data['unknown_media'] || '') - @warning_media = Oj.load(rule_data['warning_media'] || '') - @critical_media = Oj.load(rule_data['critical_media'] || '') + @entities = Flapjack.load_json(rule_data['entities'] || '') + @regex_entities = Flapjack.load_json(rule_data['regex_entities'] || '') + @time_restrictions = Flapjack.load_json(rule_data['time_restrictions'] || '') + @unknown_media = Flapjack.load_json(rule_data['unknown_media'] || '') + @warning_media = Flapjack.load_json(rule_data['warning_media'] || '') + @critical_media = Flapjack.load_json(rule_data['critical_media'] || '') @unknown_blackhole = ((rule_data['unknown_blackhole'] || 'false').downcase == 'true') @warning_blackhole = ((rule_data['warning_blackhole'] || 'false').downcase == 'true') @critical_blackhole = ((rule_data['critical_blackhole'] || 'false').downcase == 'true') diff --git a/lib/flapjack/data/tag.rb b/lib/flapjack/data/tag.rb index 9f97a686b..145666afc 100644 --- a/lib/flapjack/data/tag.rb +++ b/lib/flapjack/data/tag.rb @@ -51,10 +51,6 @@ def merge(o) super(o) end - def to_json(*a) - self.to_a.to_json(*a) - end - end end end diff --git a/lib/flapjack/data/tag_set.rb b/lib/flapjack/data/tag_set.rb index 1b545c36c..930ae8a62 100644 --- a/lib/flapjack/data/tag_set.rb +++ b/lib/flapjack/data/tag_set.rb @@ -6,10 +6,6 @@ module Flapjack module Data class TagSet < ::Set - def to_json(*a) - self.to_a.to_json(*a) - end - end end end diff --git a/lib/flapjack/gateways/jabber.rb b/lib/flapjack/gateways/jabber.rb index b39f83b34..ada930549 100644 --- a/lib/flapjack/gateways/jabber.rb +++ b/lib/flapjack/gateways/jabber.rb @@ -6,7 +6,6 @@ require 'blather/client/client' require 'chronic_duration' -require 'oj' require 'flapjack/data/entity_check' require 'flapjack/redis_pool' @@ -69,7 +68,7 @@ def stop redis_uri = @redis_config[:path] || "redis://#{@redis_config[:host] || '127.0.0.1'}:#{@redis_config[:port] || '6379'}/#{@redis_config[:db] || '0'}" shutdown_redis = EM::Hiredis.connect(redis_uri) - shutdown_redis.rpush(@config['queue'], Oj.dump('notification_type' => 'shutdown')) + shutdown_redis.rpush(@config['queue'], Flapjack.dump_json('notification_type' => 'shutdown')) end def setup @@ -695,7 +694,7 @@ def start events[queue] = @redis.blpop(queue, 0) event_json = events[queue][1] begin - event = Oj.load(event_json) + event = Flapjack.load_json(event_json) @logger.debug('jabber notification event received: ' + event.inspect) diff --git a/lib/flapjack/gateways/jsonapi.rb b/lib/flapjack/gateways/jsonapi.rb index de770950f..5932bfaf2 100644 --- a/lib/flapjack/gateways/jsonapi.rb +++ b/lib/flapjack/gateways/jsonapi.rb @@ -115,7 +115,7 @@ def initialize(resource) @logger.error "Error: #{msg_str}" end - response_body = {:errors => msg}.to_json + response_body = Flapjack.dump_json(:errors => msg) query_string = (request_info[:query_string].respond_to?(:length) && request_info[:query_string].length > 0) ? "?#{request_info[:query_string]}" : "" @@ -256,7 +256,7 @@ def cors_headers def err(status, *msg) msg_str = msg.join(", ") logger.info "Error: #{msg_str}" - [status, {}, {:errors => msg}.to_json] + [status, {}, Flapjack.dump_json(:errors => msg)] end def is_json_request? diff --git a/lib/flapjack/gateways/jsonapi/check_methods.rb b/lib/flapjack/gateways/jsonapi/check_methods.rb index 7a464b27f..b02a174cb 100644 --- a/lib/flapjack/gateways/jsonapi/check_methods.rb +++ b/lib/flapjack/gateways/jsonapi/check_methods.rb @@ -80,7 +80,7 @@ def self.registered(app) response.headers['Location'] = "#{request.base_url}/checks/#{check_names.join(',')}" status 201 - check_names.to_json + Flapjack.dump_json(check_names) end app.patch %r{^/checks/(.+)$} do diff --git a/lib/flapjack/gateways/jsonapi/contact_methods.rb b/lib/flapjack/gateways/jsonapi/contact_methods.rb index 0dbfcee6a..7ae922cfd 100644 --- a/lib/flapjack/gateways/jsonapi/contact_methods.rb +++ b/lib/flapjack/gateways/jsonapi/contact_methods.rb @@ -93,7 +93,7 @@ def self.registered(app) response.headers['Location'] = "#{base_url}/contacts/#{contact_ids.join(',')}" status 201 - contact_ids.to_json + Flapjack.dump_json(contact_ids) end # Returns all (/contacts) or some (/contacts/1,2,3) or one (/contacts/2) contact(s) diff --git a/lib/flapjack/gateways/jsonapi/entity_methods.rb b/lib/flapjack/gateways/jsonapi/entity_methods.rb index c0900f92f..53cfe4653 100644 --- a/lib/flapjack/gateways/jsonapi/entity_methods.rb +++ b/lib/flapjack/gateways/jsonapi/entity_methods.rb @@ -92,7 +92,7 @@ def self.registered(app) response.headers['Location'] = "#{request.base_url}/entities/#{entity_ids.join(',')}" status 201 - entity_ids.to_json + Flapjack.dump_json(entity_ids) end app.patch '/entities/:id' do diff --git a/lib/flapjack/gateways/jsonapi/medium_methods.rb b/lib/flapjack/gateways/jsonapi/medium_methods.rb index ab835012c..e30598152 100644 --- a/lib/flapjack/gateways/jsonapi/medium_methods.rb +++ b/lib/flapjack/gateways/jsonapi/medium_methods.rb @@ -90,7 +90,7 @@ def self.registered(app) status 201 response.headers['Location'] = "#{base_url}/media/#{media_ids.join(',')}" - media_ids.to_json + Flapjack.dump_json(media_ids) end # get one or more media records; media ids are, for Flapjack @@ -127,7 +127,7 @@ def self.registered(app) memo end - '{"media":' + media_data.to_json + '}' + '{"media":' + Flapjack.dump_json(media_data) + '}' end # update one or more media records; media ids are, for Flapjack diff --git a/lib/flapjack/gateways/jsonapi/metrics_methods.rb b/lib/flapjack/gateways/jsonapi/metrics_methods.rb index 4d1ac71d9..25aeff8f4 100644 --- a/lib/flapjack/gateways/jsonapi/metrics_methods.rb +++ b/lib/flapjack/gateways/jsonapi/metrics_methods.rb @@ -88,7 +88,7 @@ def self.registered(app) metrics[key] = self.send(key.to_sym) end - return metrics.to_json + Flapjack.dump_json(metrics) end end diff --git a/lib/flapjack/gateways/jsonapi/notification_rule_methods.rb b/lib/flapjack/gateways/jsonapi/notification_rule_methods.rb index f33b9e27a..d3c278b25 100644 --- a/lib/flapjack/gateways/jsonapi/notification_rule_methods.rb +++ b/lib/flapjack/gateways/jsonapi/notification_rule_methods.rb @@ -67,7 +67,7 @@ def self.registered(app) unless rule_ids.empty? response.headers['Location'] = "#{base_url}/notification_rules/#{rule_ids.join(',')}" - rule_ids.to_json + Flapjack.dump_json(rule_ids) end end diff --git a/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb b/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb index 1f253c6f8..ab55035a3 100644 --- a/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb +++ b/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb @@ -61,7 +61,7 @@ def self.registered(app) status 201 response.headers['Location'] = "#{base_url}/pagerduty_credentials/#{contact.id}" - [contact.id].to_json + Flapjack.dump_json([contact.id]) end app.get %r{^/pagerduty_credentials(?:/)?([^/]+)?$} do @@ -83,7 +83,7 @@ def self.registered(app) memo end - '{"pagerduty_credentials":' + pagerduty_credentials_data.to_json + '}' + '{"pagerduty_credentials":' + Flapjack.dump_json(pagerduty_credentials_data) + '}' end # update one or more sets of pagerduty credentials diff --git a/lib/flapjack/gateways/jsonapi/rack/json_params_parser.rb b/lib/flapjack/gateways/jsonapi/rack/json_params_parser.rb index f2d8e1962..215b53802 100644 --- a/lib/flapjack/gateways/jsonapi/rack/json_params_parser.rb +++ b/lib/flapjack/gateways/jsonapi/rack/json_params_parser.rb @@ -13,7 +13,7 @@ def call(env) env['rack.request.form_input'] = env['rack.input'] json_data = env['rack.input'].read env['rack.input'].rewind - data = json_data.empty? ? {} : Oj.load(json_data) + data = json_data.empty? ? {} : Flapjack.load_json(json_data) env['rack.request.form_hash'] = data.empty? ? {} : (('application/json-patch+json'.eql?(t)) ? {'ops' => data} : data) end diff --git a/lib/flapjack/gateways/jsonapi/report_methods.rb b/lib/flapjack/gateways/jsonapi/report_methods.rb index 0a53cd34b..68c85a3eb 100644 --- a/lib/flapjack/gateways/jsonapi/report_methods.rb +++ b/lib/flapjack/gateways/jsonapi/report_methods.rb @@ -121,9 +121,9 @@ def self.registered(app) } end - "{\"#{action}_reports\":" + report_data.to_json + "," + - "\"linked\":{\"entities\":" + entity_data.to_json + "," + - "\"checks\":" + check_data.to_json + "}}" + "{\"#{action}_reports\":" + Flapjack.dump_json(report_data) + "," + + "\"linked\":{\"entities\":" + Flapjack.dump_json(entity_data) + "," + + "\"checks\":" + Flapjack.dump_json(check_data) + "}}" end end diff --git a/lib/flapjack/gateways/oobetet.rb b/lib/flapjack/gateways/oobetet.rb index e5b7e61e4..5a28553f8 100644 --- a/lib/flapjack/gateways/oobetet.rb +++ b/lib/flapjack/gateways/oobetet.rb @@ -4,7 +4,6 @@ require 'eventmachine' require 'em-synchrony' require 'blather/client/client' -require 'oj' require 'flapjack/utility' @@ -210,9 +209,9 @@ def say(to, msg, using = :chat) end def send_pagerduty_event(event) - options = { :body => Oj.dump(event) } + options = { :body => Flapjack.dump_json(event) } http = EM::HttpRequest.new(@pagerduty_events_api_url).post(options) - response = Oj.load(http.response) + response = Flapjack.load_json(http.response) status = http.response_header.status @logger.debug "send_pagerduty_event got a return code of #{status.to_s} - #{response.inspect}" [status, response] diff --git a/lib/flapjack/gateways/pagerduty.rb b/lib/flapjack/gateways/pagerduty.rb index 36ba2ff8a..32d6a82aa 100644 --- a/lib/flapjack/gateways/pagerduty.rb +++ b/lib/flapjack/gateways/pagerduty.rb @@ -4,8 +4,6 @@ require 'em-synchrony' require 'em-synchrony/em-http' -require 'oj' - require 'flapjack/data/entity_check' require 'flapjack/data/alert' require 'flapjack/redis_pool' @@ -40,7 +38,7 @@ def stop redis_uri = @redis_config[:path] || "redis://#{@redis_config[:host] || '127.0.0.1'}:#{@redis_config[:port] || '6379'}/#{@redis_config[:db] || '0'}" shutdown_redis = EM::Hiredis.connect(redis_uri) - shutdown_redis.rpush(@config['queue'], Oj.dump('notification_type' => 'shutdown')) + shutdown_redis.rpush(@config['queue'], Flapjack.dump_json('notification_type' => 'shutdown')) end def start @@ -67,7 +65,7 @@ def start event_json = events[queue][1] begin - event = Oj.load(event_json) + event = Flapjack.load_json(event_json) @logger.debug("pagerduty notification event received: " + event.inspect) if 'shutdown'.eql?(event['notification_type']) @@ -163,9 +161,9 @@ def test_pagerduty_connection end def send_pagerduty_event(event) - options = { :body => Oj.dump(event) } + options = { :body => Flapjack.dump_json(event) } http = EM::HttpRequest.new(PAGERDUTY_EVENTS_API_URL).post(options) - response = Oj.load(http.response) + response = Flapjack.load_json(http.response) status = http.response_header.status @logger.debug "send_pagerduty_event got a return code of #{status.to_s} - #{response.inspect}" unless status == 200 @@ -260,7 +258,7 @@ def pagerduty_acknowledged?(opts) http = EM::HttpRequest.new(url).get(options) begin - response = Oj.load(http.response) + response = Flapjack.load_json(http.response) rescue Oj::Error @logger.error("failed to parse json from a post to #{url} ... response headers and body follows...") return nil diff --git a/lib/flapjack/gateways/web.rb b/lib/flapjack/gateways/web.rb index ddee7cd69..e6237aea2 100755 --- a/lib/flapjack/gateways/web.rb +++ b/lib/flapjack/gateways/web.rb @@ -211,7 +211,7 @@ def logger self_stats entity_stats check_stats - { + json_data = { 'events_queued' => @events_queued, 'all_entities' => @count_current_entities, 'failing_entities' => @count_failing_entities, @@ -231,7 +231,8 @@ def logger 'boottime' => @boot_time, 'current_time' => Time.now, 'executive_instances' => @executive_instances, - }.to_json + } + Flapjack.dump_json(json_data) end get '/entities_all' do diff --git a/lib/flapjack/notifier.rb b/lib/flapjack/notifier.rb index 27eabcfca..136820143 100644 --- a/lib/flapjack/notifier.rb +++ b/lib/flapjack/notifier.rb @@ -4,8 +4,6 @@ require 'em-hiredis' -require 'oj' - require 'flapjack/data/contact' require 'flapjack/data/entity_check' require 'flapjack/data/notification' @@ -79,7 +77,7 @@ def stop redis_uri = @redis_config[:path] || "redis://#{@redis_config[:host] || '127.0.0.1'}:#{@redis_config[:port] || '6379'}/#{@redis_config[:db] || '0'}" shutdown_redis = EM::Hiredis.connect(redis_uri) - shutdown_redis.rpush(@notifications_queue, Oj.dump('type' => 'shutdown')) + shutdown_redis.rpush(@notifications_queue, Flapjack.dump_json('type' => 'shutdown')) end private @@ -171,7 +169,7 @@ def process_notification(notification) when :sns Resque.enqueue_to(@queues['sns'], Flapjack::Gateways::AwsSns, contents) else - @redis.rpush(@queues[media_type.to_s], Oj.dump(contents)) + @redis.rpush(@queues[media_type.to_s], Flapjack.dump_json(contents)) end end end diff --git a/lib/flapjack/processor.rb b/lib/flapjack/processor.rb index 7097fe9fb..5aab13c25 100755 --- a/lib/flapjack/processor.rb +++ b/lib/flapjack/processor.rb @@ -129,7 +129,7 @@ def stop redis_uri = @redis_config[:path] || "redis://#{@redis_config[:host] || '127.0.0.1'}:#{@redis_config[:port] || '6379'}/#{@redis_config[:db] || '0'}" shutdown_redis = EM::Hiredis.connect(redis_uri) - shutdown_redis.rpush('events', Oj.dump('type' => 'noop')) + shutdown_redis.rpush('events', Flapjack.dump_json('type' => 'noop')) end end diff --git a/spec/lib/flapjack/data/notification_rule_spec.rb b/spec/lib/flapjack/data/notification_rule_spec.rb index 702dec31f..6042eb07d 100644 --- a/spec/lib/flapjack/data/notification_rule_spec.rb +++ b/spec/lib/flapjack/data/notification_rule_spec.rb @@ -90,8 +90,10 @@ it "generates a JSON string representing its data" do rule = existing_rule - # bit of extra hackery for the inserted ID values - expect(rule.to_json).to eq({:id => rule.id}.merge(rule_data).to_json) + # bit of extra hackery for the ID values + munged = {:id => rule.id}.merge(rule_data) + munged[:links] = {:contacts => [munged.delete(:contact_id)]} + expect(rule.to_jsonapi).to eq(Flapjack.dump_json(munged)) end it "checks whether entity names match" do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 61ee8be50..60408727f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,7 +4,6 @@ add_filter '/spec/' end SimpleCov.at_exit do - Oj.default_options = { :mode => :compat } SimpleCov.result.format! end end @@ -19,11 +18,6 @@ require 'bundler' Bundler.require(:default, :test) -require 'oj' -Oj.default_options = { :indent => 0, :mode => :strict } -Oj.mimic_JSON -require 'active_support/json' - require 'webmock/rspec' WebMock.disable_net_connect! diff --git a/spec/support/jsonapi_helper.rb b/spec/support/jsonapi_helper.rb index 9c0f9cd62..984042501 100644 --- a/spec/support/jsonapi_helper.rb +++ b/spec/support/jsonapi_helper.rb @@ -51,7 +51,7 @@ def app expect(last_response.headers.keys).to include('Access-Control-Allow-Methods') expect(last_response.headers['Access-Control-Allow-Origin']).to eq("*") unless last_response.status == 204 - expect(Oj.load(last_response.body)).to be_a(Enumerable) + expect(Flapjack.load_json(last_response.body)).to be_a(Enumerable) expect(last_response.headers['Content-Type']).to eq(Flapjack::Gateways::JSONAPI::JSONAPI_MEDIA_TYPE) end end diff --git a/tasks/benchmarks.rake b/tasks/benchmarks.rake index f672bd0be..e3ed2dd83 100644 --- a/tasks/benchmarks.rake +++ b/tasks/benchmarks.rake @@ -1,5 +1,4 @@ require 'redis' -require 'oj' require 'time' # add lib to the default include path @@ -36,7 +35,7 @@ namespace :benchmarks do desc "nukes the redis db, generates the events, runs and shuts down flapjack, generates perftools reports" task :run => [:setup, :reset_redis, :benchmark, :run_flapjack, :reports] do - puts Oj.dump(@benchmark_data, :indent => 2) + puts Flapjack.dump_json(@benchmark_data, :indent => 2) end desc "reset the redis database" @@ -76,7 +75,7 @@ namespace :benchmarks do @benchmark_data = { 'events_created' => @events_created, 'flapjack_runtime' => @timer_flapjack, 'processing_rate' => @events_created.to_f / @timer_flapjack }.merge(@benchmark_parameters) - bytes_written = IO.write('artifacts/benchmark_data.json', Oj.dump(@benchmark_data, :indent => 2)) + bytes_written = IO.write('artifacts/benchmark_data.json', Flapjack.dump_json(@benchmark_data, :indent => 2)) puts "benchmark data written to artifacts/benchmark_data.json (#{bytes_written} bytes)" if system("pprof.rb --text artifacts/flapjack-perftools-cpuprofile > artifacts/flapjack-perftools-cpuprofile.txt") diff --git a/tasks/profile.rake b/tasks/profile.rake index bdc72eac5..9e6dcbe25 100644 --- a/tasks/profile.rake +++ b/tasks/profile.rake @@ -278,7 +278,7 @@ namespace :profile do contents = msg.contents contents['event_count'] = n redis.rpush(config_env['jabber_gateway']['queue'], - Oj.dump(contents)) + Flapjack.dump_json(contents)) end end diff --git a/tmp/acknowledge.rb b/tmp/acknowledge.rb index 1df49f088..517833cf9 100644 --- a/tmp/acknowledge.rb +++ b/tmp/acknowledge.rb @@ -2,9 +2,6 @@ require 'redis' -require 'oj' -Oj.default_options = { :indent => 0, :mode => :strict } - if not id = ARGV.first then puts "Usage: acknowledge.rb " exit 1 diff --git a/tmp/create_event_ok.rb b/tmp/create_event_ok.rb index 6057609a5..a3615a500 100755 --- a/tmp/create_event_ok.rb +++ b/tmp/create_event_ok.rb @@ -2,9 +2,6 @@ require 'redis' -require 'oj' -Oj.default_options = { :indent => 0, :mode => :strict } - #id = "%.2d" % (1..10).to_a[rand(9)] events = [] diff --git a/tmp/create_event_unknown.rb b/tmp/create_event_unknown.rb index 246df8c37..7a3f6688c 100755 --- a/tmp/create_event_unknown.rb +++ b/tmp/create_event_unknown.rb @@ -2,9 +2,6 @@ require 'redis' -require 'oj' -Oj.default_options = { :indent => 0, :mode => :strict } - #id = "%.2d" % (1..10).to_a[rand(9)] events = [] diff --git a/tmp/create_events_failure.rb b/tmp/create_events_failure.rb index a8fef2b44..a09623048 100755 --- a/tmp/create_events_failure.rb +++ b/tmp/create_events_failure.rb @@ -2,9 +2,6 @@ require 'redis' -require 'oj' -Oj.default_options = { :indent => 0, :mode => :strict } - id = "%.2d" % (1..10).to_a[rand(9)] events = [] diff --git a/tmp/create_events_ok.rb b/tmp/create_events_ok.rb index f55603f13..d24765956 100755 --- a/tmp/create_events_ok.rb +++ b/tmp/create_events_ok.rb @@ -2,9 +2,6 @@ require 'redis' -require 'oj' -Oj.default_options = { :indent => 0, :mode => :strict } - id = "%.2d" % (1..10).to_a[rand(9)] events = [] diff --git a/tmp/create_events_ok_fail_ack_ok.rb b/tmp/create_events_ok_fail_ack_ok.rb index bf95de10d..9d0c1f743 100755 --- a/tmp/create_events_ok_fail_ack_ok.rb +++ b/tmp/create_events_ok_fail_ack_ok.rb @@ -2,9 +2,6 @@ require 'redis' -require 'oj' -Oj.default_options = { :indent => 0, :mode => :strict } - id = "%.2d" % (1..10).to_a[rand(9)] events = [] diff --git a/tmp/create_events_ok_failure.rb b/tmp/create_events_ok_failure.rb index 5fd3c355e..9ecc33c08 100755 --- a/tmp/create_events_ok_failure.rb +++ b/tmp/create_events_ok_failure.rb @@ -2,14 +2,11 @@ require 'redis' -require 'oj' -Oj.default_options = { :indent => 0, :mode => :compat } - id = "%.2d" % (1..10).to_a[rand(9)] events = [] -events << Oj.dump({ +events << Flapjack.dump_json({ 'entity' => "app-#{id}", 'check' => 'http', 'type' => 'service', @@ -17,7 +14,7 @@ 'summary' => 'well i don\'t know', }) -events << Oj.dump({ +events << Flapjack.dump_json({ 'entity' => "app-#{id}", 'check' => 'http', 'type' => 'host', diff --git a/tmp/create_events_ok_failure_ack.rb b/tmp/create_events_ok_failure_ack.rb index 2ba34f7a5..e8eff025d 100755 --- a/tmp/create_events_ok_failure_ack.rb +++ b/tmp/create_events_ok_failure_ack.rb @@ -2,9 +2,6 @@ require 'redis' -require 'oj' -Oj.default_options = { :indent => 0, :mode => :strict } - id = "%.2d" % (1..10).to_a[rand(9)] events = [] diff --git a/tmp/test_json_post.rb b/tmp/test_json_post.rb index 459a9759f..4f5fb7efa 100755 --- a/tmp/test_json_post.rb +++ b/tmp/test_json_post.rb @@ -2,8 +2,7 @@ require 'httparty' -require 'oj' -Oj.default_options = { :indent => 0, :mode => :strict } +require 'flapjack' @payload ={ "email" => "phil@gmail.com", @@ -14,5 +13,7 @@ "auto_action" => "true" } -HTTParty.post( 'http://localhost:4091/notification_rules', :body => Oj.dump(@payload), :options => { :headers => { 'ContentType' => 'application/json' } }) +HTTParty.post( 'http://localhost:4091/notification_rules', + :body => Flapjack.dump_json(@payload), + :options => { :headers => { 'ContentType' => 'application/json' } }) diff --git a/tmp/test_notification_rules_api.rb b/tmp/test_notification_rules_api.rb index 2c236e334..f0bbc4f27 100755 --- a/tmp/test_notification_rules_api.rb +++ b/tmp/test_notification_rules_api.rb @@ -2,8 +2,7 @@ require 'httparty' -require 'oj' -Oj.default_options = { :indent => 0, :mode => :strict } +require 'flapjack' class Foo @@ -155,7 +154,7 @@ def self.do_delete(url) do_post(url, data) end - rule = Oj.load(get('/contacts/21/notification_rules').body).last + rule = Flapjack.load_json(get('/contacts/21/notification_rules').body).last rule_id = rule['id'] raise RuntimeError unless rule_id puts "****** NOTIFICATION RULE ID TO PICK ON (PUT, DELETE) IS: #{rule_id} ******" From 726843a7f5fe55f4a746c8c9a04a699d400ced32 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Tue, 23 Sep 2014 17:01:43 +0930 Subject: [PATCH 12/69] bugfix, exception not handled as expected --- lib/flapjack/gateways/jsonapi.rb | 3 + .../pacts/flapjack-diner_v1.0.json | 554 ++++++++++++------ 2 files changed, 377 insertions(+), 180 deletions(-) diff --git a/lib/flapjack/gateways/jsonapi.rb b/lib/flapjack/gateways/jsonapi.rb index aa72dbb83..7bfbec7d3 100644 --- a/lib/flapjack/gateways/jsonapi.rb +++ b/lib/flapjack/gateways/jsonapi.rb @@ -162,6 +162,9 @@ def initialize(resource) rescue_error.call(404, e, request_info, "could not find notification rules '" + e.notification_rule_ids.join(', ') + "'") when Flapjack::Gateways::JSONAPI::EntityNotFound rescue_error.call(404, e, request_info, "could not find entity '#{e.entity}'") + when Flapjack::Gateways::JSONAPI::EntitiesNotFound + entity_ids = "'" + e.entity_ids.join("', '") + "'" + rescue_error.call(404, e, request_info, "could not find entities: #{entity_ids}") when Flapjack::Gateways::JSONAPI::EntityCheckNotFound rescue_error.call(404, e, request_info, "could not find entity check '#{e.check}'") when Flapjack::Gateways::JSONAPI::EntityChecksNotFound diff --git a/spec/service_consumers/pacts/flapjack-diner_v1.0.json b/spec/service_consumers/pacts/flapjack-diner_v1.0.json index 432e7ec7f..0c929385a 100644 --- a/spec/service_consumers/pacts/flapjack-diner_v1.0.json +++ b/spec/service_consumers/pacts/flapjack-diner_v1.0.json @@ -7,69 +7,102 @@ }, "interactions": [ { - "description": "a POST request with one check", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/checks", + "method": "get", + "path": "/checks/www.example.com:SSH" + }, + "response": { + "status": 404, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ - { - "name": "PING", - "entity_id": "1234" - } + "errors": [ + "could not find entity checks: 'www.example.com:SSH'" ] } + } + }, + { + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/checks/www.example.com:SSH" }, "response": { - "status": 201, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - "www.example.com:PING" - ] + "body": { + "checks": [ + { + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } + } + ] + } } }, { - "description": "a POST request with two checks", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/checks", + "method": "get", + "path": "/checks" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { "checks": [ { + "id": "www.example.com:SSH", "name": "SSH", - "entity_id": "1234" - }, - { - "name": "PING", - "entity_id": "1234" + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } } ] } + } + }, + { + "description": "a GET request for all checks", + "provider_state": "no entity exists", + "request": { + "method": "get", + "path": "/checks" }, "response": { - "status": 201, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - "www.example.com:SSH", - "www.example.com:PING" - ] + "body": { + "checks": [ + + ] + } } }, { "description": "a PATCH request for a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "provider_state": "no entity exists", "request": { "method": "patch", "path": "/checks/www.example.com:SSH", @@ -85,13 +118,20 @@ ] }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { "description": "a PATCH request for a single check", - "provider_state": "no entity exists", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "patch", "path": "/checks/www.example.com:SSH", @@ -107,70 +147,96 @@ ] }, "response": { - "status": 404, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two checks", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/checks", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find entity 'www.example.com'" + "checks": [ + { + "name": "SSH", + "entity_id": "1234" + }, + { + "name": "PING", + "entity_id": "1234" + } ] } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:SSH", + "www.example.com:PING" + ] } }, { - "description": "a GET request for all checks", - "provider_state": "no entity exists", + "description": "a POST request with one check", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/checks" - }, - "response": { - "status": 200, + "method": "post", + "path": "/checks", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { "checks": [ - + { + "name": "PING", + "entity_id": "1234" + } ] } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:PING" + ] } }, { - "description": "a GET request for all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a single contact", + "provider_state": "no contact exists", "request": { "method": "get", - "path": "/checks" + "path": "/contacts/abc" }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ - { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } - } + "errors": [ + "could not find contacts 'abc'" ] } } }, { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a single contact", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "get", - "path": "/checks/www.example.com:SSH" + "path": "/contacts/abc" }, "response": { "status": 200, @@ -178,65 +244,66 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ + "contacts": [ { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] } ] } } }, { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "no entity exists", + "description": "a GET request for all contacts", + "provider_state": "no contact exists", "request": { "method": "get", - "path": "/checks/www.example.com:SSH" + "path": "/contacts" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find entity checks: 'www.example.com:SSH'" + "contacts": [ + ] } } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "no contact exists", + "description": "a GET request for all contacts", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "patch", - "path": "/contacts/323", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] + "method": "get", + "path": "/contacts" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find contacts '323'" + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + } ] } } @@ -264,11 +331,11 @@ } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a PATCH request to change properties for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { "method": "patch", - "path": "/contacts/abc", + "path": "/contacts/abc,872", "headers": { "Content-Type": "application/json-patch+json" }, @@ -308,11 +375,40 @@ } }, { - "description": "a PATCH request to change properties for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a PATCH request to change properties for a single contact", + "provider_state": "no contact exists", "request": { "method": "patch", - "path": "/contacts/abc,872", + "path": "/contacts/323", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts '323'" + ] + } + } + }, + { + "description": "a PATCH request to change properties for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "patch", + "path": "/contacts/abc", "headers": { "Content-Type": "application/json-patch+json" }, @@ -330,7 +426,53 @@ } }, { - "description": "a POST request with one contact", + "description": "a DELETE request for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", + "request": { + "method": "delete", + "path": "/contacts/abc,872", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts 'abc'" + ] + } + } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two contacts", "provider_state": "no contact exists", "request": { "method": "post", @@ -350,6 +492,12 @@ "admin", "night_shift" ] + }, + { + "id": "def", + "first_name": "Joan", + "last_name": "Smith", + "email": "joans@example.com" } ] } @@ -360,12 +508,13 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "abc" + "abc", + "def" ] } }, { - "description": "a POST request with two contacts", + "description": "a POST request with one contact", "provider_state": "no contact exists", "request": { "method": "post", @@ -385,12 +534,6 @@ "admin", "night_shift" ] - }, - { - "id": "def", - "first_name": "Joan", - "last_name": "Smith", - "email": "joans@example.com" } ] } @@ -401,31 +544,16 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "abc", - "def" + "abc" ] } }, { - "description": "a DELETE request for a single contact", - "provider_state": "a contact with id 'abc' exists", - "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a single contact", - "provider_state": "no contact exists", + "description": "a GET request for a single entity", + "provider_state": "no entity exists", "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null + "method": "get", + "path": "/entities/1234" }, "response": { "status": 404, @@ -434,30 +562,17 @@ }, "body": { "errors": [ - "could not find contacts 'abc'" + "could not find entities: '1234'" ] } } }, { - "description": "a DELETE request for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", - "request": { - "method": "delete", - "path": "/contacts/abc,872", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a GET request for all contacts", - "provider_state": "a contact with id 'abc' exists", + "description": "a GET request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "get", - "path": "/contacts" + "path": "/entities/1234" }, "response": { "status": 200, @@ -465,28 +580,21 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "contacts": [ + "entities": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "name": "www.example.com", + "id": "1234" } ] } } }, { - "description": "a GET request for all contacts", - "provider_state": "no contact exists", + "description": "a GET request for all entities", + "provider_state": "no entity exists", "request": { "method": "get", - "path": "/contacts" + "path": "/entities" }, "response": { "status": 200, @@ -494,18 +602,18 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "contacts": [ + "entities": [ ] } } }, { - "description": "a GET request for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a GET request for all entities", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "get", - "path": "/contacts/abc" + "path": "/entities" }, "response": { "status": 200, @@ -513,28 +621,31 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "contacts": [ + "entities": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "name": "www.example.com", + "id": "1234" } ] } } }, { - "description": "a GET request for a single contact", - "provider_state": "no contact exists", + "description": "a PATCH request for a single entity", + "provider_state": "no entity exists", "request": { - "method": "get", - "path": "/contacts/abc" + "method": "patch", + "path": "/entities/1234", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/entities/0/name", + "value": "example3.com" + } + ] }, "response": { "status": 404, @@ -543,10 +654,93 @@ }, "body": { "errors": [ - "could not find contacts 'abc'" + "could not find entity '1234'" ] } } + }, + { + "description": "a PATCH request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "patch", + "path": "/entities/1234", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/entities/0/name", + "value": "example3.com" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two entities", + "provider_state": "no entity exists", + "request": { + "method": "post", + "path": "/entities", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "entities": [ + { + "name": "example.org", + "id": "57_example" + }, + { + "name": "example2.org", + "id": "58" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example", + "58" + ] + } + }, + { + "description": "a POST request with one entity", + "provider_state": "no entity exists", + "request": { + "method": "post", + "path": "/entities", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "entities": [ + { + "name": "example.org", + "id": "57_example" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example" + ] + } } ], "metadata": { From 5aed9fb48e335d4f491908f6c40a0bdf246173ce Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Wed, 24 Sep 2014 09:51:26 +0930 Subject: [PATCH 13/69] fix #653, overuse of Redis KEYS in mirror --- lib/flapjack/cli/receiver.rb | 39 ++++-- lib/flapjack/data/event.rb | 1 + spec/lib/flapjack/data/event_spec.rb | 172 +++++++++++++++------------ 3 files changed, 122 insertions(+), 90 deletions(-) diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index 0e868ba28..781d06cd2 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -336,8 +336,17 @@ def mirror_receive(opts) source_redis = Redis.new(:url => opts[:source]) + # refresh the key name cache, avoid repeated calls to redis KEYS + # this cache will be updated any time a new archive bucket is created + archive_keys = source_redis.keys("events_archive:*").group_by do |ak| + (source_redis.scard(ak) > 0) ? 't' : 'f' + end + + source_redis.srem('known_events_archive_keys', archive_keys['f']) unless archive_keys['f'].empty? + source_redis.sadd('known_events_archive_keys', archive_keys['t']) unless archive_keys['t'].empty? + archives = mirror_get_archive_keys_stats(source_redis) - raise "found no archives!" unless archives && archives.length > 0 + raise "found no archives!" if archives.empty? puts "found archives: #{archives.inspect}" @@ -376,15 +385,19 @@ def mirror_receive(opts) puts "\narchive key: #{archive_key}, cursor: #{cursor}" # do we need to look at the next archive bucket? archives = mirror_get_archive_keys_stats(source_redis) - i = archives.index {|a| a[:name] == archive_key } - if archives[i][:size] = (cursor.abs + 1) - if archives[i + 1] - archive_key = archives[i + 1][:name] - puts archive_key - cursor = -1 - new_archive_key = true - else - return unless opts[:follow] + + unless archives.empty? + i = archives.index {|a| a[:name] == archive_key } || 0 + + if ((archives[i][:size] == (cursor.abs + 1)) || (archives[i][:size] == 0)) + if archives[i + 1].nil? + return unless opts[:follow] + else + archive_key = archives[i + 1][:name] + puts archive_key + cursor = -1 + new_archive_key = true + end end end sleep 1 unless new_archive_key @@ -393,9 +406,9 @@ def mirror_receive(opts) end def mirror_get_archive_keys_stats(source_redis) - source_redis.keys("events_archive:*").sort.map {|a| - { :name => a, - :size => source_redis.llen(a) } + source_redis.smembers('known_events_archive_keys').sort.map {|eak| + { :name => eak, + :size => source_redis.llen(eak) } } end diff --git a/lib/flapjack/data/event.rb b/lib/flapjack/data/event.rb index df3999230..05b1be6f3 100755 --- a/lib/flapjack/data/event.rb +++ b/lib/flapjack/data/event.rb @@ -89,6 +89,7 @@ def self.next(queue, opts = {}) raw = redis.rpoplpush(queue, archive_dest) return unless raw end + redis.sadd("known_events_archive_keys", archive_dest) else if options[:block] raw = redis.brpop(queue, 0)[1] diff --git a/spec/lib/flapjack/data/event_spec.rb b/spec/lib/flapjack/data/event_spec.rb index 29d6b6d01..e51f415c3 100644 --- a/spec/lib/flapjack/data/event_spec.rb +++ b/spec/lib/flapjack/data/event_spec.rb @@ -5,7 +5,7 @@ let(:entity_name) { 'xyz-example.com' } let(:check) { 'ping' } - let(:mock_redis) { double(::Redis) } + let(:redis) { double(::Redis) } let!(:time) { Time.now} @@ -25,66 +25,72 @@ context 'class' do it "returns the next event (blocking, archiving)" do - expect(mock_redis).to receive(:brpoplpush). + expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(event_data.to_json) - expect(mock_redis).to receive(:expire) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) + expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, - :archive_events => true, :redis => mock_redis) + :archive_events => true, :redis => redis) expect(result).to be_an_instance_of(Flapjack::Data::Event) end it "returns the next event (blocking, not archiving)" do - expect(mock_redis).to receive(:brpop).with('events', 0). + expect(redis).to receive(:brpop).with('events', 0). and_return(['events', event_data.to_json]) result = Flapjack::Data::Event.next('events',:block => true, - :archive_events => false, :redis => mock_redis) + :archive_events => false, :redis => redis) expect(result).to be_an_instance_of(Flapjack::Data::Event) end it "returns the next event (non-blocking, archiving)" do - expect(mock_redis).to receive(:rpoplpush). + expect(redis).to receive(:rpoplpush). with('events', /^events_archive:/).and_return(event_data.to_json) - expect(mock_redis).to receive(:expire) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) + expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => false, - :archive_events => true, :redis => mock_redis) + :archive_events => true, :redis => redis) expect(result).to be_an_instance_of(Flapjack::Data::Event) end it "returns the next event (non-blocking, not archiving)" do - expect(mock_redis).to receive(:rpop).with('events'). + expect(redis).to receive(:rpop).with('events'). and_return(event_data.to_json) result = Flapjack::Data::Event.next('events', :block => false, - :archive_events => false, :redis => mock_redis) + :archive_events => false, :redis => redis) expect(result).to be_an_instance_of(Flapjack::Data::Event) end it "rejects invalid event JSON (archiving)" do bad_event_json = '{{{' - expect(mock_redis).to receive(:brpoplpush). + expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) - expect(mock_redis).to receive(:multi) - expect(mock_redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) - expect(mock_redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) - expect(mock_redis).to receive(:exec) - expect(mock_redis).to receive(:expire) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) + expect(redis).to receive(:multi) + expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) + expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) + expect(redis).to receive(:exec) + expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, - :archive_events => true, :redis => mock_redis) + :archive_events => true, :redis => redis) expect(result).to be_nil end it "rejects invalid event JSON (not archiving)" do bad_event_json = '{{{' - expect(mock_redis).to receive(:brpop).with('events', 0). + expect(redis).to receive(:brpop).with('events', 0). and_return(['events', bad_event_json]) - expect(mock_redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) + expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) result = Flapjack::Data::Event.next('events', :block => true, - :archive_events => false, :redis => mock_redis) + :archive_events => false, :redis => redis) expect(result).to be_nil end @@ -94,16 +100,18 @@ bad_event_data = event_data.clone bad_event_data.delete(required_key) bad_event_json = bad_event_data.to_json - expect(mock_redis).to receive(:brpoplpush). + expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) - expect(mock_redis).to receive(:multi) - expect(mock_redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) - expect(mock_redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) - expect(mock_redis).to receive(:exec) - expect(mock_redis).to receive(:expire) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) + expect(redis).to receive(:multi) + expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) + expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) + expect(redis).to receive(:exec) + expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, - :archive_events => true, :redis => mock_redis) + :archive_events => true, :redis => redis) expect(result).to be_nil end @@ -111,12 +119,12 @@ bad_event_data = event_data.clone bad_event_data.delete(required_key) bad_event_json = bad_event_data.to_json - expect(mock_redis).to receive(:brpop).with('events', 0). + expect(redis).to receive(:brpop).with('events', 0). and_return(['events', bad_event_json]) - expect(mock_redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) + expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) result = Flapjack::Data::Event.next('events', :block => true, - :archive_events => false, :redis => mock_redis) + :archive_events => false, :redis => redis) expect(result).to be_nil end @@ -124,16 +132,18 @@ bad_event_data = event_data.clone bad_event_data[required_key] = {'hello' => 'there'} bad_event_json = bad_event_data.to_json - expect(mock_redis).to receive(:brpoplpush). + expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) - expect(mock_redis).to receive(:multi) - expect(mock_redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) - expect(mock_redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) - expect(mock_redis).to receive(:exec) - expect(mock_redis).to receive(:expire) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) + expect(redis).to receive(:multi) + expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) + expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) + expect(redis).to receive(:exec) + expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, - :archive_events => true, :redis => mock_redis) + :archive_events => true, :redis => redis) expect(result).to be_nil end @@ -141,12 +151,12 @@ bad_event_data = event_data.clone bad_event_data[required_key] = {'hello' => 'there'} bad_event_json = bad_event_data.to_json - expect(mock_redis).to receive(:brpop).with('events', 0). + expect(redis).to receive(:brpop).with('events', 0). and_return(['events', bad_event_json]) - expect(mock_redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) + expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) result = Flapjack::Data::Event.next('events', :block => true, - :archive_events => false, :redis => mock_redis) + :archive_events => false, :redis => redis) expect(result).to be_nil end end @@ -156,16 +166,18 @@ bad_event_data = event_data.clone bad_event_data[optional_key] = {'hello' => 'there'} bad_event_json = bad_event_data.to_json - expect(mock_redis).to receive(:brpoplpush). + expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) - expect(mock_redis).to receive(:multi) - expect(mock_redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) - expect(mock_redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) - expect(mock_redis).to receive(:exec) - expect(mock_redis).to receive(:expire) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) + expect(redis).to receive(:multi) + expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) + expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) + expect(redis).to receive(:exec) + expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, - :archive_events => true, :redis => mock_redis) + :archive_events => true, :redis => redis) expect(result).to be_nil end @@ -173,12 +185,12 @@ bad_event_data = event_data.clone bad_event_data[optional_key] = {'hello' => 'there'} bad_event_json = bad_event_data.to_json - expect(mock_redis).to receive(:brpop).with('events', 0). + expect(redis).to receive(:brpop).with('events', 0). and_return(['events', bad_event_json]) - expect(mock_redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) + expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) result = Flapjack::Data::Event.next('events', :block => true, - :archive_events => false, :redis => mock_redis) + :archive_events => false, :redis => redis) expect(result).to be_nil end end @@ -188,23 +200,25 @@ it "it matches case-insensitively for #{key} (archiving)" do case_event_data = event_data.clone case_event_data[key] = event_data[key].upcase - expect(mock_redis).to receive(:brpoplpush). + expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(case_event_data.to_json) - expect(mock_redis).to receive(:expire) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) + expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, - :archive_events => true, :redis => mock_redis) + :archive_events => true, :redis => redis) expect(result).to be_an_instance_of(Flapjack::Data::Event) end it "it matches case-insensitively for #{key} (not archiving)" do case_event_data = event_data.clone case_event_data[key] = event_data[key].upcase - expect(mock_redis).to receive(:brpop).with('events', 0). + expect(redis).to receive(:brpop).with('events', 0). and_return(['events', case_event_data.to_json]) result = Flapjack::Data::Event.next('events',:block => true, - :archive_events => false, :redis => mock_redis) + :archive_events => false, :redis => redis) expect(result).to be_an_instance_of(Flapjack::Data::Event) end end @@ -214,23 +228,25 @@ it "it accepts an event with a numeric #{key} key (archiving)" do num_event_data = event_data.clone num_event_data[key] = event_data[key].to_i.to_s - expect(mock_redis).to receive(:brpoplpush). + expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(num_event_data.to_json) - expect(mock_redis).to receive(:expire) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) + expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, - :archive_events => true, :redis => mock_redis) + :archive_events => true, :redis => redis) expect(result).to be_an_instance_of(Flapjack::Data::Event) end it "it accepts an event with a numeric #{key} key (not archiving)" do num_event_data = event_data.clone num_event_data[key] = event_data[key].to_i.to_s - expect(mock_redis).to receive(:brpop).with('events', 0). + expect(redis).to receive(:brpop).with('events', 0). and_return(['events', num_event_data.to_json]) result = Flapjack::Data::Event.next('events',:block => true, - :archive_events => false, :redis => mock_redis) + :archive_events => false, :redis => redis) expect(result).to be_an_instance_of(Flapjack::Data::Event) end @@ -238,16 +254,18 @@ bad_event_data = event_data.clone bad_event_data[key] = 'NaN' bad_event_json = bad_event_data.to_json - expect(mock_redis).to receive(:brpoplpush). + expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) - expect(mock_redis).to receive(:multi) - expect(mock_redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) - expect(mock_redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) - expect(mock_redis).to receive(:exec) - expect(mock_redis).to receive(:expire) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) + expect(redis).to receive(:multi) + expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) + expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) + expect(redis).to receive(:exec) + expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, - :archive_events => true, :redis => mock_redis) + :archive_events => true, :redis => redis) expect(result).to be_nil end @@ -255,12 +273,12 @@ bad_event_data = event_data.clone bad_event_data[key] = 'NaN' bad_event_json = bad_event_data.to_json - expect(mock_redis).to receive(:brpop).with('events', 0). + expect(redis).to receive(:brpop).with('events', 0). and_return(['events', bad_event_json]) - expect(mock_redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) + expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) result = Flapjack::Data::Event.next('events', :block => true, - :archive_events => false, :redis => mock_redis) + :archive_events => false, :redis => redis) expect(result).to be_nil end @@ -268,26 +286,26 @@ it "returns a count of pending events" do events_len = 23 - expect(mock_redis).to receive(:llen).with('events').and_return(events_len) + expect(redis).to receive(:llen).with('events').and_return(events_len) - pc = Flapjack::Data::Event.pending_count('events', :redis => mock_redis) + pc = Flapjack::Data::Event.pending_count('events', :redis => redis) expect(pc).to eq(events_len) end it "creates a notification testing event" do expect(Time).to receive(:now).and_return(time) - expect(mock_redis).to receive(:lpush).with('events', /"testing"/ ) + expect(redis).to receive(:lpush).with('events', /"testing"/ ) Flapjack::Data::Event.test_notifications(entity_name, check, - :summary => 'test', :details => 'testing', :redis => mock_redis) + :summary => 'test', :details => 'testing', :redis => redis) end it "creates an acknowledgement event" do expect(Time).to receive(:now).and_return(time) - expect(mock_redis).to receive(:lpush).with('events', /"acking"/ ) + expect(redis).to receive(:lpush).with('events', /"acking"/ ) Flapjack::Data::Event.create_acknowledgement(entity_name, check, - :summary => 'acking', :time => time.to_i, :redis => mock_redis) + :summary => 'acking', :time => time.to_i, :redis => redis) end end From 0fd511a7b6c51ef71a70c17b503d39a522e57210 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Wed, 24 Sep 2014 15:21:40 +0930 Subject: [PATCH 14/69] pacts for maintenance period behaviour --- .../pacts/flapjack-diner_v1.0.json | 1211 +++++++++++++---- .../provider_states_for_flapjack-diner.rb | 44 + 2 files changed, 987 insertions(+), 268 deletions(-) diff --git a/spec/service_consumers/pacts/flapjack-diner_v1.0.json b/spec/service_consumers/pacts/flapjack-diner_v1.0.json index 0c929385a..fa42b3dff 100644 --- a/spec/service_consumers/pacts/flapjack-diner_v1.0.json +++ b/spec/service_consumers/pacts/flapjack-diner_v1.0.json @@ -7,11 +7,11 @@ }, "interactions": [ { - "description": "a GET request for check 'www.example.com:SSH'", + "description": "a GET request for a single entity", "provider_state": "no entity exists", "request": { "method": "get", - "path": "/checks/www.example.com:SSH" + "path": "/entities/1234" }, "response": { "status": 404, @@ -20,17 +20,17 @@ }, "body": { "errors": [ - "could not find entity checks: 'www.example.com:SSH'" + "could not find entities: '1234'" ] } } }, { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "get", - "path": "/checks/www.example.com:SSH" + "path": "/entities/1234" }, "response": { "status": 200, @@ -38,27 +38,21 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ + "entities": [ { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } + "name": "www.example.com", + "id": "1234" } ] } } }, { - "description": "a GET request for all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for all entities", + "provider_state": "no entity exists", "request": { "method": "get", - "path": "/checks" + "path": "/entities" }, "response": { "status": 200, @@ -66,54 +60,109 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ + "entities": [ + + ] + } + } + }, + { + "description": "a GET request for all entities", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "get", + "path": "/entities" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "entities": [ { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } + "name": "www.example.com", + "id": "1234" } ] } } }, { - "description": "a GET request for all checks", + "description": "a POST request with two entities", "provider_state": "no entity exists", "request": { - "method": "get", - "path": "/checks" + "method": "post", + "path": "/entities", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "entities": [ + { + "name": "example.org", + "id": "57_example" + }, + { + "name": "example2.org", + "id": "58" + } + ] + } }, "response": { - "status": 200, + "status": 201, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, + "body": [ + "57_example", + "58" + ] + } + }, + { + "description": "a POST request with one entity", + "provider_state": "no entity exists", + "request": { + "method": "post", + "path": "/entities", + "headers": { + "Content-Type": "application/vnd.api+json" + }, "body": { - "checks": [ - + "entities": [ + { + "name": "example.org", + "id": "57_example" + } ] } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example" + ] } }, { - "description": "a PATCH request for a single check", + "description": "a PATCH request for a single entity", "provider_state": "no entity exists", "request": { "method": "patch", - "path": "/checks/www.example.com:SSH", + "path": "/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/checks/0/enabled", - "value": false + "path": "/entities/0/name", + "value": "example3.com" } ] }, @@ -124,25 +173,25 @@ }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find entity '1234'" ] } } }, { - "description": "a PATCH request for a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "patch", - "path": "/checks/www.example.com:SSH", + "path": "/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/checks/0/enabled", - "value": false + "path": "/entities/0/name", + "value": "example3.com" } ] }, @@ -152,23 +201,32 @@ } }, { - "description": "a POST request with two checks", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with two contacts", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/checks", + "path": "/contacts", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "contacts": [ { - "name": "SSH", - "entity_id": "1234" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] }, { - "name": "PING", - "entity_id": "1234" + "id": "def", + "first_name": "Joan", + "last_name": "Smith", + "email": "joans@example.com" } ] } @@ -179,25 +237,32 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "www.example.com:SSH", - "www.example.com:PING" + "abc", + "def" ] } }, { - "description": "a POST request with one check", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with one contact", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/checks", + "path": "/contacts", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "contacts": [ { - "name": "PING", - "entity_id": "1234" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] } ] } @@ -208,10 +273,47 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "www.example.com:PING" + "abc" ] } }, + { + "description": "a POST request with one contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "post", + "path": "/contacts", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + } + ] + } + }, + "response": { + "status": 409, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "Contacts already exist with the following IDs: abc" + ] + } + } + }, { "description": "a GET request for a single contact", "provider_state": "no contact exists", @@ -309,21 +411,12 @@ } }, { - "description": "a PATCH request to change links for two contacts", + "description": "a DELETE request for two contacts", "provider_state": "contacts with ids 'abc' and '872' exist", "request": { - "method": "patch", + "method": "delete", "path": "/contacts/abc,872", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" - } - ] + "body": null }, "response": { "status": 204, @@ -331,21 +424,12 @@ } }, { - "description": "a PATCH request to change properties for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a DELETE request for a single contact", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "patch", - "path": "/contacts/abc,872", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] + "method": "delete", + "path": "/contacts/abc", + "body": null }, "response": { "status": 204, @@ -353,25 +437,23 @@ } }, { - "description": "a PATCH requestto change a link for a single contact", - "provider_state": "a contact with id '872' exists", + "description": "a DELETE request for a single contact", + "provider_state": "no contact exists", "request": { - "method": "patch", - "path": "/contacts/872", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" - } - ] + "method": "delete", + "path": "/contacts/abc", + "body": null }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts 'abc'" + ] + } } }, { @@ -426,12 +508,21 @@ } }, { - "description": "a DELETE request for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a PATCH requestto change a link for a single contact", + "provider_state": "a contact with id '872' exists", "request": { - "method": "delete", - "path": "/contacts/abc,872", - "body": null + "method": "patch", + "path": "/contacts/872", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" + } + ] }, "response": { "status": 204, @@ -439,32 +530,21 @@ } }, { - "description": "a DELETE request for a single contact", - "provider_state": "no contact exists", + "description": "a PATCH request to change properties for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null - }, - "response": { - "status": 404, + "method": "patch", + "path": "/contacts/abc,872", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, - "body": { - "errors": [ - "could not find contacts 'abc'" - ] - } - } - }, - { - "description": "a DELETE request for a single contact", - "provider_state": "a contact with id 'abc' exists", - "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] }, "response": { "status": 204, @@ -472,88 +552,33 @@ } }, { - "description": "a POST request with two contacts", - "provider_state": "no contact exists", + "description": "a PATCH request to change links for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { - "method": "post", - "path": "/contacts", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "contacts": [ - { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] - }, - { - "id": "def", - "first_name": "Joan", - "last_name": "Smith", - "email": "joans@example.com" - } - ] - } - }, - "response": { - "status": 201, + "method": "patch", + "path": "/contacts/abc,872", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, "body": [ - "abc", - "def" + { + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" + } ] - } - }, - { - "description": "a POST request with one contact", - "provider_state": "no contact exists", - "request": { - "method": "post", - "path": "/contacts", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "contacts": [ - { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] - } - ] - } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "abc" - ] + "status": 204, + "body": "" } }, { - "description": "a GET request for a single entity", + "description": "a GET request for check 'www.example.com:SSH'", "provider_state": "no entity exists", "request": { "method": "get", - "path": "/entities/1234" + "path": "/checks/www.example.com:SSH" }, "response": { "status": 404, @@ -562,17 +587,17 @@ }, "body": { "errors": [ - "could not find entities: '1234'" + "could not find entity checks: 'www.example.com:SSH'" ] } } }, { - "description": "a GET request for a single entity", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/entities/1234" + "path": "/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -580,21 +605,27 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "entities": [ + "checks": [ { - "name": "www.example.com", - "id": "1234" + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } } ] } } }, { - "description": "a GET request for all entities", - "provider_state": "no entity exists", + "description": "a GET request for all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/entities" + "path": "/checks" }, "response": { "status": 200, @@ -602,18 +633,27 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "entities": [ - + "checks": [ + { + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } + } ] } } }, { - "description": "a GET request for all entities", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for all checks", + "provider_state": "no entity exists", "request": { "method": "get", - "path": "/entities" + "path": "/checks" }, "response": { "status": 200, @@ -621,58 +661,479 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "entities": [ - { - "name": "www.example.com", - "id": "1234" - } + "checks": [ + ] } } }, { - "description": "a PATCH request for a single entity", - "provider_state": "no entity exists", + "description": "a POST request with two checks", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "patch", - "path": "/entities/1234", + "method": "post", + "path": "/checks", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" - } - ] + "body": { + "checks": [ + { + "name": "SSH", + "entity_id": "1234" + }, + { + "name": "PING", + "entity_id": "1234" + } + ] + } }, "response": { - "status": 404, + "status": 201, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } - } - }, - { - "description": "a PATCH request for a single entity", + "body": [ + "www.example.com:SSH", + "www.example.com:PING" + ] + } + }, + { + "description": "a POST request with one check", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/checks", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "checks": [ + { + "name": "PING", + "entity_id": "1234" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:PING" + ] + } + }, + { + "description": "a PATCH request for a single check", + "provider_state": "no entity exists", + "request": { + "method": "patch", + "path": "/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/checks/0/enabled", + "value": false + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } + } + }, + { + "description": "a PATCH request for a single check", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "patch", + "path": "/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/checks/0/enabled", + "value": false + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-24T15:15:15+09:30" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-24T15:15:15+09:30" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no check exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-24T15:15:15+09:30" + } + ] + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } + } + }, + { + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-24T15:15:15+09:30", + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "request": { + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-24T15:15:15+09:30", + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "request": { + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-24T15:15:15+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-24T17:15:15+09:30", + "duration": 3600, + "summary": "more work" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-24T15:15:15+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-24T17:15:15+09:30", + "duration": 3600, + "summary": "more work" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "query": "start_time=2014-09-24T15%3A15%3A15%2B09%3A30" + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-24T15%3A15%3A15%2B09%3A30" + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no check exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-24T15%3A15%3A15%2B09%3A30" + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/entities/1234,5678", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-24T15:15:15+09:30" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "patch", - "path": "/entities/1234", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-24T15:15:15+09:30" } ] }, @@ -682,64 +1143,278 @@ } }, { - "description": "a POST request with two entities", + "description": "a PATCH request for an unscheduled maintenance period", "provider_state": "no entity exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-24T15:15:15+09:30" + } + ] + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } + } + }, + { + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/entities", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "unscheduled_maintenances": [ { - "name": "example.org", - "id": "57_example" + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/entities/1234,5678", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/entities/1234,5678", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" }, { - "name": "example2.org", - "id": "58" + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 201, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, - "body": [ - "57_example", - "58" - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a POST request with one entity", - "provider_state": "no entity exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/entities", + "path": "/scheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "scheduled_maintenances": [ { - "name": "example.org", - "id": "57_example" + "start_time": "2014-09-24T15:15:15+09:30", + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 201, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, - "body": [ - "57_example" - ] + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-24T15:15:15+09:30", + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-24T15:15:15+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-24T17:15:15+09:30", + "duration": 3600, + "summary": "more work" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/scheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-24T15:15:15+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-24T17:15:15+09:30", + "duration": 3600, + "summary": "more work" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/entities/1234,5678", + "query": "start_time=2014-09-24T15%3A15%3A15%2B09%3A30" + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-24T15%3A15%3A15%2B09%3A30" + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no entity exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-24T15%3A15%3A15%2B09%3A30" + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } } } ], diff --git a/spec/service_consumers/provider_states_for_flapjack-diner.rb b/spec/service_consumers/provider_states_for_flapjack-diner.rb index b8d11d275..723c4bff4 100644 --- a/spec/service_consumers/provider_states_for_flapjack-diner.rb +++ b/spec/service_consumers/provider_states_for_flapjack-diner.rb @@ -16,6 +16,14 @@ end end + provider_state "no check exists" do + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end + provider_state "an entity 'www.example.com' with id '1234' exists" do set_up do redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') @@ -31,6 +39,23 @@ end end + provider_state "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist" do + set_up do + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + + entity_data = {'id' => '1234', 'name' => 'www.example.com'} + Flapjack::Data::Entity.add(entity_data, :redis => redis) + entity_data_2 = {'id' => '5678', 'name' => 'www2.example.com'} + Flapjack::Data::Entity.add(entity_data_2, :redis => redis) + end + + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end + provider_state "a check 'www.example.com:SSH' exists" do set_up do redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') @@ -48,6 +73,25 @@ end end + provider_state "checks 'www.example.com:SSH' and 'www.example.com:PING' exist" do + set_up do + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + + entity_data = {'id' => '1234', 'name' => 'www.example.com'} + Flapjack::Data::Entity.add(entity_data, :redis => redis) + check_data = {'entity_id' => '1234', 'name' => 'SSH'} + Flapjack::Data::EntityCheck.add(check_data, :redis => redis) + check_data_2 = {'entity_id' => '1234', 'name' => 'PING'} + Flapjack::Data::EntityCheck.add(check_data_2, :redis => redis) + end + + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end + provider_state "a contact with id 'abc' exists" do set_up do redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') From fa7f8bb3aca25526b58c195f45ccc6a4dd402191 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Wed, 24 Sep 2014 17:01:20 +0930 Subject: [PATCH 15/69] WIP pacts for media --- .../gateways/jsonapi/medium_methods.rb | 6 +- .../pacts/flapjack-diner_v1.0.json | 1610 ++++++++++------- .../provider_states_for_flapjack-diner.rb | 40 + 3 files changed, 977 insertions(+), 679 deletions(-) diff --git a/lib/flapjack/gateways/jsonapi/medium_methods.rb b/lib/flapjack/gateways/jsonapi/medium_methods.rb index ab835012c..a3161fabb 100644 --- a/lib/flapjack/gateways/jsonapi/medium_methods.rb +++ b/lib/flapjack/gateways/jsonapi/medium_methods.rb @@ -115,12 +115,14 @@ def self.registered(app) media_list_cache[contact.id] ||= contact.media_list if media_list_cache[contact.id].include?(media_type) medium_id = "#{contact.id}_#{media_type}" + int = contact.media_intervals[media_type] + rut = contact.media_rollup_thresholds[media_type] memo << {:id => medium_id, :type => media_type, :address => contact.media[media_type], - :interval => contact.media_intervals[media_type], - :rollup_threshold => contact.media_rollup_thresholds[media_type], + :interval => int.nil? ? nil : int.to_i, + :rollup_threshold => rut.nil? ? nil : rut.to_i, :links => {:contacts => [contact.id]}} end diff --git a/spec/service_consumers/pacts/flapjack-diner_v1.0.json b/spec/service_consumers/pacts/flapjack-diner_v1.0.json index fa42b3dff..4c3b63605 100644 --- a/spec/service_consumers/pacts/flapjack-diner_v1.0.json +++ b/spec/service_consumers/pacts/flapjack-diner_v1.0.json @@ -7,191 +7,247 @@ }, "interactions": [ { - "description": "a GET request for a single entity", - "provider_state": "no entity exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/entities/1234" + "method": "post", + "path": "/scheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-24T17:00:16+09:30", + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { - "status": 404, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find entities: '1234'" + "scheduled_maintenances": [ + { + "start_time": "2014-09-24T17:00:16+09:30", + "duration": 3600, + "summary": "working" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a single entity", + "description": "a POST request with two scheduled maintenance periods", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/entities/1234" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "scheduled_maintenances": [ { - "name": "www.example.com", - "id": "1234" + "start_time": "2014-09-24T17:00:16+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-24T19:00:16+09:30", + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for all entities", - "provider_state": "no entity exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/entities" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ - + "scheduled_maintenances": [ + { + "start_time": "2014-09-24T17:00:16+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-24T19:00:16+09:30", + "duration": 3600, + "summary": "more work" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for all entities", + "description": "a POST request with one unscheduled maintenance period", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/entities" + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "unscheduled_maintenances": [ { - "name": "www.example.com", - "id": "1234" + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a POST request with two entities", - "provider_state": "no entity exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/entities", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "unscheduled_maintenances": [ { - "name": "example.org", - "id": "57_example" + "duration": 3600, + "summary": "working" }, { - "name": "example2.org", - "id": "58" + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "57_example", - "58" - ] + "status": 204, + "body": "" } }, { - "description": "a POST request with one entity", - "provider_state": "no entity exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/entities", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "unscheduled_maintenances": [ { - "name": "example.org", - "id": "57_example" + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "57_example" - ] + "status": 204, + "body": "" } }, { - "description": "a PATCH request for a single entity", - "provider_state": "no entity exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "patch", - "path": "/entities/1234", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-24T17:00:16+09:30" } ] }, "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } + "status": 204, + "body": "" } }, { - "description": "a PATCH request for a single entity", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "patch", - "path": "/entities/1234", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-24T17:00:16+09:30" } ] }, @@ -201,45 +257,391 @@ } }, { - "description": "a POST request with two contacts", - "provider_state": "no contact exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/contacts", + "method": "patch", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-24T17:00:16+09:30" + } + ] + }, + "response": { + "status": 404, "body": { - "contacts": [ - { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] - }, - { - "id": "def", - "first_name": "Joan", - "last_name": "Smith", - "email": "joans@example.com" - } + "errors": [ + "could not find entity '1234'" ] } - }, + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-24T17%3A00%3A16%2B09%3A30" + }, "response": { - "status": 201, + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/entities/1234,5678", + "query": "start_time=2014-09-24T17%3A00%3A16%2B09%3A30" + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no entity exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-24T17%3A00%3A16%2B09%3A30" + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-24T17:00:16+09:30", + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "request": { + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-24T17:00:16+09:30", + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-24T17:00:16+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-24T19:00:16+09:30", + "duration": 3600, + "summary": "more work" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "request": { + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-24T17:00:16+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-24T19:00:16+09:30", + "duration": 3600, + "summary": "more work" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" }, "body": [ - "abc", - "def" + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-24T17:00:16+09:30" + } ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-24T17:00:16+09:30" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no check exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-24T17:00:16+09:30" + } + ] + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-24T17%3A00%3A16%2B09%3A30" + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "query": "start_time=2014-09-24T17%3A00%3A16%2B09%3A30" + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no check exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-24T17%3A00%3A16%2B09%3A30" + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { @@ -278,8 +680,8 @@ } }, { - "description": "a POST request with one contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with two contacts", + "provider_state": "no contact exists", "request": { "method": "post", "path": "/contacts", @@ -298,47 +700,70 @@ "admin", "night_shift" ] + }, + { + "id": "def", + "first_name": "Joan", + "last_name": "Smith", + "email": "joans@example.com" } ] } }, "response": { - "status": 409, + "status": 201, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": { - "errors": [ - "Contacts already exist with the following IDs: abc" - ] - } + "body": [ + "abc", + "def" + ] } }, { - "description": "a GET request for a single contact", - "provider_state": "no contact exists", + "description": "a POST request with one contact", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "get", - "path": "/contacts/abc" + "method": "post", + "path": "/contacts", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + } + ] + } }, "response": { - "status": 404, + "status": 409, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { "errors": [ - "could not find contacts 'abc'" + "Contacts already exist with the following IDs: abc" ] } } }, { - "description": "a GET request for a single contact", + "description": "a GET request for all contacts", "provider_state": "a contact with id 'abc' exists", "request": { "method": "get", - "path": "/contacts/abc" + "path": "/contacts" }, "response": { "status": 200, @@ -382,11 +807,11 @@ } }, { - "description": "a GET request for all contacts", + "description": "a GET request for a single contact", "provider_state": "a contact with id 'abc' exists", "request": { "method": "get", - "path": "/contacts" + "path": "/contacts/abc" }, "response": { "status": 200, @@ -411,49 +836,44 @@ } }, { - "description": "a DELETE request for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a GET request for a single contact", + "provider_state": "no contact exists", "request": { - "method": "delete", - "path": "/contacts/abc,872", - "body": null + "method": "get", + "path": "/contacts/abc" }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts 'abc'" + ] + } } }, { - "description": "a DELETE request for a single contact", + "description": "a PATCH request to change properties for a single contact", "provider_state": "a contact with id 'abc' exists", "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a single contact", - "provider_state": "no contact exists", - "request": { - "method": "delete", + "method": "patch", "path": "/contacts/abc", - "body": null + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] }, "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find contacts 'abc'" - ] - } + "status": 204, + "body": "" } }, { @@ -486,11 +906,11 @@ } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a PATCH request to change properties for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { "method": "patch", - "path": "/contacts/abc", + "path": "/contacts/abc,872", "headers": { "Content-Type": "application/json-patch+json" }, @@ -529,28 +949,6 @@ "body": "" } }, - { - "description": "a PATCH request to change properties for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", - "request": { - "method": "patch", - "path": "/contacts/abc,872", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] - }, - "response": { - "status": 204, - "body": "" - } - }, { "description": "a PATCH request to change links for two contacts", "provider_state": "contacts with ids 'abc' and '872' exist", @@ -574,101 +972,53 @@ } }, { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "no entity exists", - "request": { - "method": "get", - "path": "/checks/www.example.com:SSH" - }, - "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find entity checks: 'www.example.com:SSH'" - ] - } - } - }, - { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for a single contact", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "get", - "path": "/checks/www.example.com:SSH" + "method": "delete", + "path": "/contacts/abc", + "body": null }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "checks": [ - { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a GET request for all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { - "method": "get", - "path": "/checks" + "method": "delete", + "path": "/contacts/abc,872", + "body": null }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "checks": [ - { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a GET request for all checks", - "provider_state": "no entity exists", + "description": "a DELETE request for a single contact", + "provider_state": "no contact exists", "request": { - "method": "get", - "path": "/checks" + "method": "delete", + "path": "/contacts/abc", + "body": null }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ - + "errors": [ + "could not find contacts 'abc'" ] } } }, { - "description": "a POST request with two checks", + "description": "a POST request with one check", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", @@ -678,10 +1028,6 @@ }, "body": { "checks": [ - { - "name": "SSH", - "entity_id": "1234" - }, { "name": "PING", "entity_id": "1234" @@ -695,13 +1041,12 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "www.example.com:SSH", "www.example.com:PING" ] } }, { - "description": "a POST request with one check", + "description": "a POST request with two checks", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", @@ -711,6 +1056,10 @@ }, "body": { "checks": [ + { + "name": "SSH", + "entity_id": "1234" + }, { "name": "PING", "entity_id": "1234" @@ -724,225 +1073,121 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ + "www.example.com:SSH", "www.example.com:PING" ] } }, { - "description": "a PATCH request for a single check", + "description": "a GET request for all checks", "provider_state": "no entity exists", "request": { - "method": "patch", - "path": "/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/checks/0/enabled", - "value": false - } - ] + "method": "get", + "path": "/checks" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find entity 'www.example.com'" - ] - } - } - }, - { - "description": "a PATCH request for a single check", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "patch", - "path": "/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/checks/0/enabled", - "value": false - } - ] - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", - "request": { - "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-24T15:15:15+09:30" - } - ] - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-24T15:15:15+09:30" - } - ] - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no check exists", - "request": { - "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-24T15:15:15+09:30" - } - ] - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity 'www.example.com'" + "checks": [ + ] } } }, { - "description": "a POST request with one unscheduled maintenance period", + "description": "a GET request for all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/checks" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "checks": [ { - "duration": 3600, - "summary": "working" + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "method": "get", + "path": "/checks/www.example.com:SSH" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "checks": [ { - "duration": 3600, - "summary": "working" + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "method": "get", + "path": "/checks/www.example.com:SSH" + }, + "response": { + "status": 404, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, - { - "duration": 3600, - "summary": "more work" - } + "errors": [ + "could not find entity checks: 'www.example.com:SSH'" ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", + "description": "a PATCH request for a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "method": "patch", + "path": "/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, - { - "duration": 3600, - "summary": "more work" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/checks/0/enabled", + "value": false + } + ] }, "response": { "status": 204, @@ -950,190 +1195,191 @@ } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request for a single check", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "method": "patch", + "path": "/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/checks/0/enabled", + "value": false + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-24T15:15:15+09:30", - "duration": 3600, - "summary": "working" - } + "errors": [ + "could not find entity 'www.example.com'" ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a POST request with one entity", + "provider_state": "no entity exists", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "path": "/entities", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "entities": [ { - "start_time": "2014-09-24T15:15:15+09:30", - "duration": 3600, - "summary": "working" + "name": "example.org", + "id": "57_example" } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example" + ] } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a POST request with two entities", + "provider_state": "no entity exists", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "path": "/entities", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "entities": [ { - "start_time": "2014-09-24T15:15:15+09:30", - "duration": 3600, - "summary": "working" + "name": "example.org", + "id": "57_example" }, { - "start_time": "2014-09-24T17:15:15+09:30", - "duration": 3600, - "summary": "more work" + "name": "example2.org", + "id": "58" } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example", + "58" + ] } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for all entities", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/entities" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-24T15:15:15+09:30", - "duration": 3600, - "summary": "working" - }, + "entities": [ { - "start_time": "2014-09-24T17:15:15+09:30", - "duration": 3600, - "summary": "more work" + "name": "www.example.com", + "id": "1234" } ] } - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", - "query": "start_time=2014-09-24T15%3A15%3A15%2B09%3A30" - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for all entities", + "provider_state": "no entity exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-24T15%3A15%3A15%2B09%3A30" + "method": "get", + "path": "/entities" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "entities": [ + + ] + } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no check exists", + "description": "a GET request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-24T15%3A15%3A15%2B09%3A30" + "method": "get", + "path": "/entities/1234" }, "response": { - "status": 404, + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { - "errors": [ - "could not find entity 'www.example.com'" + "entities": [ + { + "name": "www.example.com", + "id": "1234" + } ] } } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for a single entity", + "provider_state": "no entity exists", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/entities/1234,5678", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-24T15:15:15+09:30" - } - ] + "method": "get", + "path": "/entities/1234" }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entities: '1234'" + ] + } } }, { - "description": "a PATCH request for an unscheduled maintenance period", + "description": "a PATCH request for a single entity", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", + "path": "/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-24T15:15:15+09:30" + "path": "/entities/0/name", + "value": "example3.com" } ] }, @@ -1143,24 +1389,27 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", + "description": "a PATCH request for a single entity", "provider_state": "no entity exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", + "path": "/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-24T15:15:15+09:30" + "path": "/entities/0/name", + "value": "example3.com" } ] }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ "could not find entity '1234'" @@ -1169,205 +1418,202 @@ } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with one medium", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "path": "/contacts/abc/media", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "media": [ { - "duration": 3600, - "summary": "working" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 } ] } }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", - "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "status": 201, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } - ] - } - }, - "response": { - "status": 204, - "body": "" + "body": [ + "abc_sms" + ] } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a POST request with two media", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "path": "/contacts/abc/media", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "media": [ { - "duration": 3600, - "summary": "working" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 }, { - "duration": 3600, - "summary": "more work" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3 } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc_sms", + "abc_email" + ] } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for all media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "method": "get", + "path": "/media" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "media": [ { - "duration": 3600, - "summary": "working" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3, + "links": { + "contacts": [ + "abc" + ] + } }, { - "duration": 3600, - "summary": "more work" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-24T15:15:15+09:30", - "duration": 3600, - "summary": "working" - } - ] - } + "method": "get", + "path": "/media/abc_sms" }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", - "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "media": [ { - "start_time": "2014-09-24T15:15:15+09:30", - "duration": 3600, - "summary": "working" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "method": "get", + "path": "/media/abc_email,abc_sms" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "media": [ { - "start_time": "2014-09-24T15:15:15+09:30", - "duration": 3600, - "summary": "working" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3, + "links": { + "contacts": [ + "abc" + ] + } }, { - "start_time": "2014-09-24T17:15:15+09:30", - "duration": 3600, - "summary": "more work" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a PATCH request for email media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "method": "patch", + "path": "/media/abc_email", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-24T15:15:15+09:30", - "duration": 3600, - "summary": "working" - }, - { - "start_time": "2014-09-24T17:15:15+09:30", - "duration": 3600, - "summary": "more work" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/media/0/interval", + "value": 50 + }, + { + "op": "replace", + "path": "/media/0/rollup_threshold", + "value": 3 + } + ] }, "response": { "status": 204, @@ -1375,12 +1621,26 @@ } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a PATCH request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234,5678", - "query": "start_time=2014-09-24T15%3A15%3A15%2B09%3A30" + "method": "patch", + "path": "/media/abc_email,abc_sms", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/media/0/interval", + "value": 50 + }, + { + "op": "replace", + "path": "/media/0/rollup_threshold", + "value": 3 + } + ] }, "response": { "status": 204, @@ -1388,12 +1648,12 @@ } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a DELETE request for one medium", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-24T15%3A15%3A15%2B09%3A30" + "path": "/media/abc_email", + "body": null }, "response": { "status": 204, @@ -1401,20 +1661,16 @@ } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no entity exists", + "description": "a DELETE request for two media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-24T15%3A15%3A15%2B09%3A30" + "path": "/media/abc_email,abc_sms", + "body": null }, "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } + "status": 204, + "body": "" } } ], diff --git a/spec/service_consumers/provider_states_for_flapjack-diner.rb b/spec/service_consumers/provider_states_for_flapjack-diner.rb index 723c4bff4..6cb740f85 100644 --- a/spec/service_consumers/provider_states_for_flapjack-diner.rb +++ b/spec/service_consumers/provider_states_for_flapjack-diner.rb @@ -111,6 +111,46 @@ end end + provider_state "a contact with id 'abc' has email and sms media" do + set_up do + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + contact_data = {'id' => 'abc', + 'first_name' => 'Jim', + 'last_name' => 'Smith', + 'email' => 'jims@example.com', + 'timezone' => 'UTC', + 'tags' => ['admin', 'night_shift']} + contact = Flapjack::Data::Contact.add(contact_data, :redis => redis) + + email_data = { + 'type' => 'email', + 'address' => 'ablated@example.org', + 'interval' => 180, + 'rollup_threshold' => 3 + } + + sms_data = { + 'type' => 'sms', + 'address' => '0123456789', + 'interval' => 300, + 'rollup_threshold' => 5 + } + + [email_data, sms_data].each do |medium_data| + type = medium_data['type'] + contact.set_address_for_media(type, medium_data['address']) + contact.set_interval_for_media(type, medium_data['interval']) + contact.set_rollup_threshold_for_media(type, medium_data['rollup_threshold']) + end + end + + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end + provider_state "a contact with id '872' exists" do set_up do redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') From d8718443ee7cc7fd9f939ed744cac22c360af115 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Thu, 25 Sep 2014 09:52:57 +0930 Subject: [PATCH 16/69] more media pacts --- .../gateways/jsonapi/medium_methods.rb | 6 +- .../pacts/flapjack-diner_v1.0.json | 1512 +++++++++-------- 2 files changed, 809 insertions(+), 709 deletions(-) diff --git a/lib/flapjack/gateways/jsonapi/medium_methods.rb b/lib/flapjack/gateways/jsonapi/medium_methods.rb index a3161fabb..ec7367d27 100644 --- a/lib/flapjack/gateways/jsonapi/medium_methods.rb +++ b/lib/flapjack/gateways/jsonapi/medium_methods.rb @@ -42,8 +42,8 @@ def split_media_ids(media_ids) contact_id = $1 media_type = $2 - halt err(422, "Could not get contact_id from media_id") if contact_id.nil? - halt err(422, "Could not get media type from media_id") if media_type.nil? + halt err(422, "Could not get contact_id from media_id '#{m_id}'") if contact_id.nil? + halt err(422, "Could not get media type from media_id '#{m_id}'") if media_type.nil? contact_cache[contact_id] ||= find_contact(contact_id) @@ -73,7 +73,7 @@ def self.registered(app) contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis) if contact.nil? semaphore.release - halt err(422, "Contact id:'#{params[:contact_id]}' could not be loaded") + halt err(422, "Contact id: '#{params[:contact_id]}' could not be loaded") end media_data.each do |medium_data| diff --git a/spec/service_consumers/pacts/flapjack-diner_v1.0.json b/spec/service_consumers/pacts/flapjack-diner_v1.0.json index 4c3b63605..180a8c43e 100644 --- a/spec/service_consumers/pacts/flapjack-diner_v1.0.json +++ b/spec/service_consumers/pacts/flapjack-diner_v1.0.json @@ -7,247 +7,191 @@ }, "interactions": [ { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for a single entity", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-24T17:00:16+09:30", - "duration": 3600, - "summary": "working" - } - ] - } + "method": "get", + "path": "/entities/1234" }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", - "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "status": 404, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-24T17:00:16+09:30", - "duration": 3600, - "summary": "working" - } + "errors": [ + "could not find entities: '1234'" ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", + "description": "a GET request for a single entity", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "method": "get", + "path": "/entities/1234" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-24T17:00:16+09:30", - "duration": 3600, - "summary": "working" - }, + "entities": [ { - "start_time": "2014-09-24T19:00:16+09:30", - "duration": 3600, - "summary": "more work" + "name": "www.example.com", + "id": "1234" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for all entities", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "method": "get", + "path": "/entities" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-24T17:00:16+09:30", - "duration": 3600, - "summary": "working" - }, - { - "start_time": "2014-09-24T19:00:16+09:30", - "duration": 3600, - "summary": "more work" - } + "entities": [ + ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", + "description": "a GET request for all entities", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } - ] - } + "method": "get", + "path": "/entities" }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", - "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "entities": [ { - "duration": 3600, - "summary": "working" + "name": "www.example.com", + "id": "1234" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with two entities", + "provider_state": "no entity exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "path": "/entities", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "entities": [ { - "duration": 3600, - "summary": "working" + "name": "example.org", + "id": "57_example" }, { - "duration": 3600, - "summary": "more work" + "name": "example2.org", + "id": "58" } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example", + "58" + ] } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a POST request with one entity", + "provider_state": "no entity exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "path": "/entities", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, + "entities": [ { - "duration": 3600, - "summary": "more work" + "name": "example.org", + "id": "57_example" } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example" + ] } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a PATCH request for a single entity", + "provider_state": "no entity exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", + "path": "/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-24T17:00:16+09:30" + "path": "/entities/0/name", + "value": "example3.com" } ] }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a PATCH request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/entities/1234,5678", + "path": "/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-24T17:00:16+09:30" + "path": "/entities/0/name", + "value": "example3.com" } ] }, @@ -257,395 +201,213 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", + "description": "a GET request for check 'www.example.com:SSH'", "provider_state": "no entity exists", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-24T17:00:16+09:30" - } - ] + "method": "get", + "path": "/checks/www.example.com:SSH" }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity '1234'" + "could not find entity checks: 'www.example.com:SSH'" ] } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-24T17%3A00%3A16%2B09%3A30" - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234,5678", - "query": "start_time=2014-09-24T17%3A00%3A16%2B09%3A30" + "method": "get", + "path": "/checks/www.example.com:SSH" }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no entity exists", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-24T17%3A00%3A16%2B09%3A30" - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } - } - }, - { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-24T17:00:16+09:30", - "duration": 3600, - "summary": "working" - } - ] - } - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", - "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "checks": [ { - "start_time": "2014-09-24T17:00:16+09:30", - "duration": 3600, - "summary": "working" + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", + "description": "a GET request for all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-24T17:00:16+09:30", - "duration": 3600, - "summary": "working" - }, - { - "start_time": "2014-09-24T19:00:16+09:30", - "duration": 3600, - "summary": "more work" - } - ] - } + "method": "get", + "path": "/checks" }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", - "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-24T17:00:16+09:30", - "duration": 3600, - "summary": "working" - }, + "checks": [ { - "start_time": "2014-09-24T19:00:16+09:30", - "duration": 3600, - "summary": "more work" + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for all checks", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } - ] - } + "method": "get", + "path": "/checks" }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", - "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } + "checks": [ + ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with two checks", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/checks", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "checks": [ { - "duration": 3600, - "summary": "working" + "name": "SSH", + "entity_id": "1234" }, { - "duration": 3600, - "summary": "more work" + "name": "PING", + "entity_id": "1234" } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:SSH", + "www.example.com:PING" + ] } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a POST request with one check", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "path": "/checks", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, + "checks": [ { - "duration": 3600, - "summary": "more work" + "name": "PING", + "entity_id": "1234" } ] } }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "status": 201, "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-24T17:00:16+09:30" - } + "www.example.com:PING" ] - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a PATCH request for a single check", + "provider_state": "no entity exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "path": "/checks/www.example.com:SSH", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-24T17:00:16+09:30" + "path": "/checks/0/enabled", + "value": false } ] }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no check exists", + "description": "a PATCH request for a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/checks/www.example.com:SSH", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-24T17:00:16+09:30" + "path": "/checks/0/enabled", + "value": false } ] }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity 'www.example.com'" - ] - } - } - }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-24T17%3A00%3A16%2B09%3A30" - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", - "query": "start_time=2014-09-24T17%3A00%3A16%2B09%3A30" - }, "response": { "status": 204, "body": "" } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no check exists", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-24T17%3A00%3A16%2B09%3A30" - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity 'www.example.com'" - ] - } - } - }, - { - "description": "a POST request with one contact", + "description": "a POST request with two contacts", "provider_state": "no contact exists", "request": { "method": "post", @@ -665,6 +427,12 @@ "admin", "night_shift" ] + }, + { + "id": "def", + "first_name": "Joan", + "last_name": "Smith", + "email": "joans@example.com" } ] } @@ -675,12 +443,13 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "abc" + "abc", + "def" ] } }, { - "description": "a POST request with two contacts", + "description": "a POST request with one contact", "provider_state": "no contact exists", "request": { "method": "post", @@ -700,12 +469,6 @@ "admin", "night_shift" ] - }, - { - "id": "def", - "first_name": "Joan", - "last_name": "Smith", - "email": "joans@example.com" } ] } @@ -716,8 +479,7 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "abc", - "def" + "abc" ] } }, @@ -759,11 +521,30 @@ } }, { - "description": "a GET request for all contacts", + "description": "a GET request for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "get", + "path": "/contacts/abc" + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts 'abc'" + ] + } + } + }, + { + "description": "a GET request for a single contact", "provider_state": "a contact with id 'abc' exists", "request": { "method": "get", - "path": "/contacts" + "path": "/contacts/abc" }, "response": { "status": 200, @@ -807,11 +588,11 @@ } }, { - "description": "a GET request for a single contact", + "description": "a GET request for all contacts", "provider_state": "a contact with id 'abc' exists", "request": { "method": "get", - "path": "/contacts/abc" + "path": "/contacts" }, "response": { "status": 200, @@ -836,11 +617,38 @@ } }, { - "description": "a GET request for a single contact", + "description": "a DELETE request for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", + "request": { + "method": "delete", + "path": "/contacts/abc,872", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a single contact", "provider_state": "no contact exists", "request": { - "method": "get", - "path": "/contacts/abc" + "method": "delete", + "path": "/contacts/abc", + "body": null }, "response": { "status": 404, @@ -854,6 +662,57 @@ } } }, + { + "description": "a PATCH request to change properties for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "patch", + "path": "/contacts/323", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts '323'" + ] + } + } + }, + { + "description": "a PATCH requestto change a link for a single contact", + "provider_state": "a contact with id '872' exists", + "request": { + "method": "patch", + "path": "/contacts/872", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, { "description": "a PATCH request to change properties for a single contact", "provider_state": "a contact with id 'abc' exists", @@ -877,11 +736,11 @@ } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "no contact exists", + "description": "a PATCH request to change properties for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { "method": "patch", - "path": "/contacts/323", + "path": "/contacts/abc,872", "headers": { "Content-Type": "application/json-patch+json" }, @@ -894,19 +753,12 @@ ] }, "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find contacts '323'" - ] - } + "status": 204, + "body": "" } }, { - "description": "a PATCH request to change properties for two contacts", + "description": "a PATCH request to change links for two contacts", "provider_state": "contacts with ids 'abc' and '872' exist", "request": { "method": "patch", @@ -916,9 +768,9 @@ }, "body": [ { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" } ] }, @@ -928,19 +780,19 @@ } }, { - "description": "a PATCH requestto change a link for a single contact", - "provider_state": "a contact with id '872' exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { "method": "patch", - "path": "/contacts/872", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T09:51:28+09:30" } ] }, @@ -950,19 +802,19 @@ } }, { - "description": "a PATCH request to change links for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "patch", - "path": "/contacts/abc,872", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T09:51:28+09:30" } ] }, @@ -972,12 +824,48 @@ } }, { - "description": "a DELETE request for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no check exists", "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T09:51:28+09:30" + } + ] + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } + } + }, + { + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 204, @@ -985,12 +873,22 @@ } }, { - "description": "a DELETE request for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "delete", - "path": "/contacts/abc,872", - "body": null + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 204, @@ -998,194 +896,222 @@ } }, { - "description": "a DELETE request for a single contact", - "provider_state": "no contact exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } }, "response": { - "status": 404, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find contacts 'abc'" + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a POST request with one check", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "post", - "path": "/checks", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "scheduled_maintenances": [ { - "name": "PING", - "entity_id": "1234" + "start_time": "2014-09-25T09:51:28+09:30", + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 201, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "request": { + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, - "body": [ - "www.example.com:PING" - ] + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-25T09:51:28+09:30", + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a POST request with two checks", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { "method": "post", - "path": "/checks", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "scheduled_maintenances": [ { - "name": "SSH", - "entity_id": "1234" + "start_time": "2014-09-25T09:51:28+09:30", + "duration": 3600, + "summary": "working" }, { - "name": "PING", - "entity_id": "1234" + "start_time": "2014-09-25T11:51:28+09:30", + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "www.example.com:SSH", - "www.example.com:PING" - ] + "status": 204, + "body": "" } }, { - "description": "a GET request for all checks", - "provider_state": "no entity exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/checks" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ - + "scheduled_maintenances": [ + { + "start_time": "2014-09-25T09:51:28+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-25T11:51:28+09:30", + "duration": 3600, + "summary": "more work" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "get", - "path": "/checks" + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "query": "start_time=2014-09-25T09%3A51%3A28%2B09%3A30" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "checks": [ - { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a GET request for check 'www.example.com:SSH'", + "description": "a DELETE request for a scheduled maintenance period", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/checks/www.example.com:SSH" + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-25T09%3A51%3A28%2B09%3A30" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "checks": [ - { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "no entity exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no check exists", "request": { - "method": "get", - "path": "/checks/www.example.com:SSH" + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-25T09%3A51%3A28%2B09%3A30" }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find entity checks: 'www.example.com:SSH'" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a PATCH request for a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "patch", - "path": "/checks/www.example.com:SSH", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/checks/0/enabled", - "value": false + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T09:51:28+09:30" } ] }, @@ -1195,193 +1121,279 @@ } }, { - "description": "a PATCH request for a single check", - "provider_state": "no entity exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "patch", - "path": "/checks/www.example.com:SSH", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/checks/0/enabled", - "value": false + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T09:51:28+09:30" } ] }, "response": { - "status": 404, + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no entity exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T09:51:28+09:30" + } + ] + }, + "response": { + "status": 404, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find entity '1234'" ] } } }, { - "description": "a POST request with one entity", - "provider_state": "no entity exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/entities", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "unscheduled_maintenances": [ { - "name": "example.org", - "id": "57_example" + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 201, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, - "body": [ - "57_example" - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a POST request with two entities", - "provider_state": "no entity exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/entities", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "unscheduled_maintenances": [ { - "name": "example.org", - "id": "57_example" + "duration": 3600, + "summary": "working" }, { - "name": "example2.org", - "id": "58" + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "57_example", - "58" - ] + "status": 204, + "body": "" } }, { - "description": "a GET request for all entities", + "description": "a POST request with two unscheduled maintenance periods", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/entities" + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "scheduled_maintenances": [ { - "name": "www.example.com", - "id": "1234" + "start_time": "2014-09-25T09:51:28+09:30", + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for all entities", - "provider_state": "no entity exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/entities" + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-25T09:51:28+09:30", + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, - "body": { - "entities": [ - + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-25T09:51:28+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-25T11:51:28+09:30", + "duration": 3600, + "summary": "more work" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a single entity", + "description": "a POST request with two scheduled maintenance periods", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/entities/1234" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "scheduled_maintenances": [ { - "name": "www.example.com", - "id": "1234" + "start_time": "2014-09-25T09:51:28+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-25T11:51:28+09:30", + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a single entity", - "provider_state": "no entity exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/entities/1234" + "method": "delete", + "path": "/scheduled_maintenances/entities/1234,5678", + "query": "start_time=2014-09-25T09%3A51%3A28%2B09%3A30" }, "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find entities: '1234'" - ] - } + "status": 204, + "body": "" } }, { - "description": "a PATCH request for a single entity", + "description": "a DELETE request for a scheduled maintenance period", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "patch", - "path": "/entities/1234", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" - } - ] + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-25T09%3A51%3A28%2B09%3A30" }, "response": { "status": 204, @@ -1389,27 +1401,15 @@ } }, { - "description": "a PATCH request for a single entity", + "description": "a DELETE request for a scheduled maintenance period", "provider_state": "no entity exists", "request": { - "method": "patch", - "path": "/entities/1234", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" - } - ] + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-25T09%3A51%3A28%2B09%3A30" }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ "could not find entity '1234'" @@ -1418,7 +1418,7 @@ } }, { - "description": "a POST request with one medium", + "description": "a POST request with two media", "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", @@ -1433,6 +1433,12 @@ "address": "0123456789", "interval": 300, "rollup_threshold": 5 + }, + { + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3 } ] } @@ -1443,12 +1449,13 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "abc_sms" + "abc_sms", + "abc_email" ] } }, { - "description": "a POST request with two media", + "description": "a POST request with one medium", "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", @@ -1463,12 +1470,6 @@ "address": "0123456789", "interval": 300, "rollup_threshold": 5 - }, - { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3 } ] } @@ -1479,11 +1480,42 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "abc_sms", - "abc_email" + "abc_sms" ] } }, + { + "description": "a POST request with one medium", + "provider_state": "no contact exists", + "request": { + "method": "post", + "path": "/contacts/abc/media", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "media": [ + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 + } + ] + } + }, + "response": { + "status": 422, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "Contact id: 'abc' could not be loaded" + ] + } + } + }, { "description": "a GET request for all media", "provider_state": "a contact with id 'abc' has email and sms media", @@ -1553,6 +1585,25 @@ } } }, + { + "description": "a GET request for sms media", + "provider_state": "no contact exists", + "request": { + "method": "get", + "path": "/media/abc_sms" + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contact 'abc'" + ] + } + } + }, { "description": "a GET request for email and sms media", "provider_state": "a contact with id 'abc' has email and sms media", @@ -1594,11 +1645,57 @@ } }, { - "description": "a PATCH request for email media", + "description": "a DELETE request for two media", "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "patch", + "method": "delete", + "path": "/media/abc_email,abc_sms", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for one medium", + "provider_state": "a contact with id 'abc' has email and sms media", + "request": { + "method": "delete", + "path": "/media/abc_email", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for one medium", + "provider_state": "no contact exists", + "request": { + "method": "delete", "path": "/media/abc_email", + "body": null + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contact 'abc'" + ] + } + } + }, + { + "description": "a PATCH request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", + "request": { + "method": "patch", + "path": "/media/abc_email,abc_sms", "headers": { "Content-Type": "application/json-patch+json" }, @@ -1621,11 +1718,11 @@ } }, { - "description": "a PATCH request for email and sms media", + "description": "a PATCH request for email media", "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "patch", - "path": "/media/abc_email,abc_sms", + "path": "/media/abc_email", "headers": { "Content-Type": "application/json-patch+json" }, @@ -1648,29 +1745,32 @@ } }, { - "description": "a DELETE request for one medium", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a PATCH request for email media", + "provider_state": "no contact exists", "request": { - "method": "delete", + "method": "patch", "path": "/media/abc_email", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for two media", - "provider_state": "a contact with id 'abc' has email and sms media", - "request": { - "method": "delete", - "path": "/media/abc_email,abc_sms", - "body": null + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/media/0/interval", + "value": 50 + } + ] }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contact 'abc'" + ] + } } } ], From 7b667d3f83b97c74ee6cad85e405d2d0f49e5690 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Thu, 25 Sep 2014 15:47:43 +0930 Subject: [PATCH 17/69] states for notification rule pacts --- .../pacts/flapjack-diner_v1.0.json | 2320 ++++++++++------- .../provider_states_for_flapjack-diner.rb | 95 + 2 files changed, 1488 insertions(+), 927 deletions(-) diff --git a/spec/service_consumers/pacts/flapjack-diner_v1.0.json b/spec/service_consumers/pacts/flapjack-diner_v1.0.json index 180a8c43e..e99b3d0ad 100644 --- a/spec/service_consumers/pacts/flapjack-diner_v1.0.json +++ b/spec/service_consumers/pacts/flapjack-diner_v1.0.json @@ -7,193 +7,212 @@ }, "interactions": [ { - "description": "a GET request for a single entity", - "provider_state": "no entity exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no check exists", "request": { - "method": "get", - "path": "/entities/1234" + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-25T15%3A46%3A26%2B09%3A30" }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find entities: '1234'" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a GET request for a single entity", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "get", - "path": "/entities/1234" + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "query": "start_time=2014-09-25T15%3A46%3A26%2B09%3A30" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "entities": [ - { - "name": "www.example.com", - "id": "1234" - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a GET request for all entities", - "provider_state": "no entity exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/entities" + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-25T15%3A46%3A26%2B09%3A30" }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no check exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T15:46:26+09:30" + } + ] + }, + "response": { + "status": 404, "body": { - "entities": [ - + "errors": [ + "could not find entity 'www.example.com'" ] } } }, { - "description": "a GET request for all entities", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "get", - "path": "/entities" + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T15:46:26+09:30" + } + ] }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, - "body": { - "entities": [ - { - "name": "www.example.com", - "id": "1234" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T15:46:26+09:30" + } + ] + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a POST request with two entities", - "provider_state": "no entity exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { "method": "post", - "path": "/entities", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "unscheduled_maintenances": [ { - "name": "example.org", - "id": "57_example" + "duration": 3600, + "summary": "working" }, { - "name": "example2.org", - "id": "58" + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "57_example", - "58" - ] + "status": 204, + "body": "" } }, { - "description": "a POST request with one entity", - "provider_state": "no entity exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "post", - "path": "/entities", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "unscheduled_maintenances": [ { - "name": "example.org", - "id": "57_example" + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "57_example" - ] + "status": 204, + "body": "" } }, { - "description": "a PATCH request for a single entity", - "provider_state": "no entity exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "patch", - "path": "/entities/1234", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" - } - ] - }, - "response": { - "status": 404, + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find entity '1234'" + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a PATCH request for a single entity", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/entities/1234", + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" - } - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 204, @@ -201,203 +220,194 @@ } }, { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "no entity exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "get", - "path": "/checks/www.example.com:SSH" - }, - "response": { - "status": 404, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find entity checks: 'www.example.com:SSH'" + "scheduled_maintenances": [ + { + "start_time": "2014-09-25T15:46:26+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-25T17:46:26+09:30", + "duration": 3600, + "summary": "more work" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for check 'www.example.com:SSH'", + "description": "a POST request with two scheduled maintenance periods", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/checks/www.example.com:SSH" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "scheduled_maintenances": [ { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } + "start_time": "2014-09-25T15:46:26+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-25T17:46:26+09:30", + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "get", - "path": "/checks" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "scheduled_maintenances": [ { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } + "start_time": "2014-09-25T15:46:26+09:30", + "duration": 3600, + "summary": "working" } ] } - } - }, - { - "description": "a GET request for all checks", - "provider_state": "no entity exists", - "request": { - "method": "get", - "path": "/checks" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "checks": [ - - ] - } + "status": 204, + "body": "" } }, { - "description": "a POST request with two checks", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "post", - "path": "/checks", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ - { - "name": "SSH", - "entity_id": "1234" - }, + "scheduled_maintenances": [ { - "name": "PING", - "entity_id": "1234" + "start_time": "2014-09-25T15:46:26+09:30", + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "www.example.com:SSH", - "www.example.com:PING" - ] + "status": 204, + "body": "" } }, { - "description": "a POST request with one check", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/checks", - "headers": { - "Content-Type": "application/vnd.api+json" - }, + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-25T15%3A46%3A26%2B09%3A30" + }, + "response": { + "status": 404, "body": { - "checks": [ - { - "name": "PING", - "entity_id": "1234" - } + "errors": [ + "could not find entity '1234'" ] } + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/entities/1234,5678", + "query": "start_time=2014-09-25T15%3A46%3A26%2B09%3A30" }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "www.example.com:PING" - ] + "status": 204, + "body": "" } }, { - "description": "a PATCH request for a single check", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-25T15%3A46%3A26%2B09%3A30" + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", "provider_state": "no entity exists", "request": { "method": "patch", - "path": "/checks/www.example.com:SSH", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/checks/0/enabled", - "value": false + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T15:46:26+09:30" } ] }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find entity '1234'" ] } } }, { - "description": "a PATCH request for a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "patch", - "path": "/checks/www.example.com:SSH", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/checks/0/enabled", - "value": false + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T15:46:26+09:30" } ] }, @@ -407,222 +417,179 @@ } }, { - "description": "a POST request with two contacts", - "provider_state": "no contact exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "post", - "path": "/contacts", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "contacts": [ - { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] - }, - { - "id": "def", - "first_name": "Joan", - "last_name": "Smith", - "email": "joans@example.com" - } - ] - } - }, - "response": { - "status": 201, + "method": "patch", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, "body": [ - "abc", - "def" + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T15:46:26+09:30" + } ] + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a POST request with one contact", - "provider_state": "no contact exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/contacts", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "unscheduled_maintenances": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "abc" - ] + "status": 204, + "body": "" } }, { - "description": "a POST request with one contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/contacts", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "unscheduled_maintenances": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 409, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "Contacts already exist with the following IDs: abc" - ] - } + "status": 204, + "body": "" } }, { - "description": "a GET request for a single contact", - "provider_state": "no contact exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/contacts/abc" - }, - "response": { - "status": 404, + "method": "post", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find contacts 'abc'" + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/contacts/abc" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "unscheduled_maintenances": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for all contacts", - "provider_state": "no contact exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/contacts" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ - + "scheduled_maintenances": [ + { + "start_time": "2014-09-25T15:46:26+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-25T17:46:26+09:30", + "duration": 3600, + "summary": "more work" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for all contacts", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/contacts" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "scheduled_maintenances": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "start_time": "2014-09-25T15:46:26+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-25T17:46:26+09:30", + "duration": 3600, + "summary": "more work" } ] } - } - }, - { - "description": "a DELETE request for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", - "request": { - "method": "delete", - "path": "/contacts/abc,872", - "body": null }, "response": { "status": 204, @@ -630,12 +597,23 @@ } }, { - "description": "a DELETE request for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-25T15:46:27+09:30", + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 204, @@ -643,39 +621,43 @@ } }, { - "description": "a DELETE request for a single contact", - "provider_state": "no contact exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null - }, - "response": { - "status": 404, + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find contacts 'abc'" + "scheduled_maintenances": [ + { + "start_time": "2014-09-25T15:46:27+09:30", + "duration": 3600, + "summary": "working" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "no contact exists", + "description": "a PATCH request for a single check", + "provider_state": "no entity exists", "request": { "method": "patch", - "path": "/contacts/323", + "path": "/checks/www.example.com:SSH", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" + "path": "/checks/0/enabled", + "value": false } ] }, @@ -686,25 +668,25 @@ }, "body": { "errors": [ - "could not find contacts '323'" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a PATCH requestto change a link for a single contact", - "provider_state": "a contact with id '872' exists", + "description": "a PATCH request for a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "patch", - "path": "/contacts/872", + "path": "/checks/www.example.com:SSH", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" + "op": "replace", + "path": "/checks/0/enabled", + "value": false } ] }, @@ -714,36 +696,215 @@ } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "no entity exists", "request": { - "method": "patch", - "path": "/contacts/abc", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] + "method": "get", + "path": "/checks/www.example.com:SSH" }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity checks: 'www.example.com:SSH'" + ] + } } }, { - "description": "a PATCH request to change properties for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/contacts/abc,872", - "headers": { - "Content-Type": "application/json-patch+json" - }, + "method": "get", + "path": "/checks/www.example.com:SSH" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "checks": [ + { + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } + } + ] + } + } + }, + { + "description": "a GET request for all checks", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/checks" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "checks": [ + { + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } + } + ] + } + } + }, + { + "description": "a GET request for all checks", + "provider_state": "no entity exists", + "request": { + "method": "get", + "path": "/checks" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "checks": [ + + ] + } + } + }, + { + "description": "a POST request with two checks", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/checks", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "checks": [ + { + "name": "SSH", + "entity_id": "1234" + }, + { + "name": "PING", + "entity_id": "1234" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:SSH", + "www.example.com:PING" + ] + } + }, + { + "description": "a POST request with one check", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/checks", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "checks": [ + { + "name": "PING", + "entity_id": "1234" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:PING" + ] + } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts 'abc'" + ] + } + } + }, + { + "description": "a DELETE request for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", + "request": { + "method": "delete", + "path": "/contacts/abc,872", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request to change properties for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "patch", + "path": "/contacts/323", + "headers": { + "Content-Type": "application/json-patch+json" + }, "body": [ { "op": "replace", @@ -753,16 +914,23 @@ ] }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts '323'" + ] + } } }, { - "description": "a PATCH request to change links for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a PATCH requestto change a link for a single contact", + "provider_state": "a contact with id '872' exists", "request": { "method": "patch", - "path": "/contacts/abc,872", + "path": "/contacts/872", "headers": { "Content-Type": "application/json-patch+json" }, @@ -780,19 +948,19 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a PATCH request to change links for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "path": "/contacts/abc,872", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T09:51:28+09:30" + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" } ] }, @@ -802,19 +970,19 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request to change properties for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/contacts/abc,872", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T09:51:28+09:30" + "path": "/contacts/0/timezone", + "value": "UTC" } ] }, @@ -824,244 +992,264 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no check exists", + "description": "a PATCH request to change properties for a single contact", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/contacts/abc", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T09:51:28+09:30" + "path": "/contacts/0/timezone", + "value": "UTC" } ] }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a GET request for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "get", + "path": "/contacts/abc" + }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find contacts 'abc'" ] } } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a single contact", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/contacts/abc" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "contacts": [ { - "duration": 3600, - "summary": "working" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a GET request for all contacts", + "provider_state": "no contact exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "method": "get", + "path": "/contacts" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } + "contacts": [ + ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a GET request for all contacts", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "method": "get", + "path": "/contacts" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, + "contacts": [ { - "duration": 3600, - "summary": "more work" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one contact", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/contacts", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, + "contacts": [ { - "duration": 3600, - "summary": "more work" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] } ] } }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "status": 409, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-25T09:51:28+09:30", - "duration": 3600, - "summary": "working" - } + "errors": [ + "Contacts already exist with the following IDs: abc" ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a POST request with two contacts", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "path": "/contacts", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "contacts": [ { - "start_time": "2014-09-25T09:51:28+09:30", - "duration": 3600, - "summary": "working" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + }, + { + "id": "def", + "first_name": "Joan", + "last_name": "Smith", + "email": "joans@example.com" } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc", + "def" + ] } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a POST request with one contact", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "path": "/contacts", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-25T09:51:28+09:30", - "duration": 3600, - "summary": "working" - }, + "contacts": [ { - "start_time": "2014-09-25T11:51:28+09:30", - "duration": 3600, - "summary": "more work" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc" + ] } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for one medium", + "provider_state": "no contact exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "method": "delete", + "path": "/media/abc_email", + "body": null + }, + "response": { + "status": 404, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-25T09:51:28+09:30", - "duration": 3600, - "summary": "working" - }, - { - "start_time": "2014-09-25T11:51:28+09:30", - "duration": 3600, - "summary": "more work" - } + "errors": [ + "could not find contact 'abc'" ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a DELETE request for two media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", - "query": "start_time=2014-09-25T09%3A51%3A28%2B09%3A30" + "path": "/media/abc_email,abc_sms", + "body": null }, "response": { "status": 204, @@ -1069,12 +1257,12 @@ } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for one medium", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-25T09%3A51%3A28%2B09%3A30" + "path": "/media/abc_email", + "body": null }, "response": { "status": 204, @@ -1082,58 +1270,53 @@ } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no check exists", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-25T09%3A51%3A28%2B09%3A30" - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity 'www.example.com'" - ] - } - } - }, - { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a PATCH request for email media", + "provider_state": "no contact exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/entities/1234,5678", + "path": "/media/abc_email", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T09:51:28+09:30" + "path": "/media/0/interval", + "value": 50 } ] }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contact 'abc'" + ] + } } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a PATCH request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", + "path": "/media/abc_email,abc_sms", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T09:51:28+09:30" + "path": "/media/0/interval", + "value": 50 + }, + { + "op": "replace", + "path": "/media/0/rollup_threshold", + "value": 3 } ] }, @@ -1143,125 +1326,299 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no entity exists", + "description": "a PATCH request for email media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", + "path": "/media/abc_email", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T09:51:28+09:30" + "path": "/media/0/interval", + "value": 50 + }, + { + "op": "replace", + "path": "/media/0/rollup_threshold", + "value": 3 } ] }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a GET request for sms media", + "provider_state": "no contact exists", + "request": { + "method": "get", + "path": "/media/abc_sms" + }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity '1234'" + "could not find contact 'abc'" ] } } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "method": "get", + "path": "/media/abc_email,abc_sms" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "media": [ { - "duration": 3600, - "summary": "working" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3, + "links": { + "contacts": [ + "abc" + ] + } + }, + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } } ] } + } + }, + { + "description": "a GET request for sms media", + "provider_state": "a contact with id 'abc' has email and sms media", + "request": { + "method": "get", + "path": "/media/abc_sms" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "media": [ + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } + } + ] + } } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for all media", + "provider_state": "a contact with id 'abc' has email and sms media", + "request": { + "method": "get", + "path": "/media" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "media": [ + { + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3, + "links": { + "contacts": [ + "abc" + ] + } + }, + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } + } + ] + } + } + }, + { + "description": "a POST request with one medium", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "path": "/contacts/abc/media", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "media": [ { - "duration": 3600, - "summary": "working" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 } ] } }, "response": { - "status": 204, - "body": "" + "status": 422, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "Contact id: 'abc' could not be loaded" + ] + } } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a POST request with two media", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "path": "/contacts/abc/media", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "media": [ { - "duration": 3600, - "summary": "working" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 }, { - "duration": 3600, - "summary": "more work" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3 } ] } }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc_sms", + "abc_email" + ] + } + }, + { + "description": "a POST request with one medium", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "post", + "path": "/contacts/abc/media", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "media": [ + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc_sms" + ] + } + }, + { + "description": "a DELETE request for a single notification rule", + "provider_state": "no notification rule exists", + "request": { + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "body": null + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" + ] + } + } + }, + { + "description": "a DELETE request for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", + "request": { + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", + "body": null + }, "response": { "status": 204, "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a DELETE request for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, - { - "duration": 3600, - "summary": "more work" - } - ] - } + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "body": null }, "response": { "status": 204, @@ -1269,23 +1626,50 @@ } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a PATCH request to change properties for a single notification rule", + "provider_state": "no notification rule exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "method": "patch", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-25T09:51:28+09:30", - "duration": 3600, - "summary": "working" - } + "errors": [ + "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" ] } + } + }, + { + "description": "a PATCH request to change properties for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", + "request": { + "method": "patch", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] }, "response": { "status": 204, @@ -1293,23 +1677,21 @@ } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a PATCH request to change properties for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "method": "patch", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-25T09:51:28+09:30", - "duration": 3600, - "summary": "working" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] }, "response": { "status": 204, @@ -1317,128 +1699,276 @@ } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for a single notification rule", + "provider_state": "no notification rule exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "method": "get", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" + }, + "response": { + "status": 404, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-25T09:51:28+09:30", - "duration": 3600, - "summary": "working" - }, - { - "start_time": "2014-09-25T11:51:28+09:30", - "duration": 3600, - "summary": "more work" - } + "errors": [ + "could not find notification rules '05983623-fcef-42da-af44-ed6990b500fa'" ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "method": "get", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "notification_rules": [ { - "start_time": "2014-09-25T09:51:28+09:30", - "duration": 3600, - "summary": "working" + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false }, { - "start_time": "2014-09-25T11:51:28+09:30", - "duration": 3600, - "summary": "more work" + "id": "20f182fc-6e32-4794-9007-97366d162c51", + "tags": [ + "physical" + ], + "regex_tags": [ + + ], + "entities": [ + "example.com" + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": true, + "critical_blackhole": true } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234,5678", - "query": "start_time=2014-09-25T09%3A51%3A28%2B09%3A30" + "method": "get", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "notification_rules": [ + { + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + } + ] + } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for all notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-25T09%3A51%3A28%2B09%3A30" + "method": "get", + "path": "/notification_rules" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "notification_rules": [ + { + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + } + ] + } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no entity exists", + "description": "a POST request with one notification rule", + "provider_state": "no contact exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-25T09%3A51%3A28%2B09%3A30" + "method": "post", + "path": "/contacts/abc/notification_rules", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "notification_rules": [ + { + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + } + ] + } }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity '1234'" + "could not find contact 'abc'" ] } } }, { - "description": "a POST request with two media", + "description": "a POST request with two notification rules", "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/contacts/abc/media", + "path": "/contacts/abc/notification_rules", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "media": [ + "notification_rules": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false }, { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3 + "entity_tags": null, + "entities": [ + "foo-app-02.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": true, + "critical_blackhole": false } ] } @@ -1449,27 +1979,52 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "abc_sms", - "abc_email" + { + "json_class": "Pact::Term", + "data": { + "generate": "05983623-fcef-42da-af44-ed6990b500fa", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + }, + { + "json_class": "Pact::Term", + "data": { + "generate": "20f182fc-6e32-4794-9007-97366d162c51", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + } ] } }, { - "description": "a POST request with one medium", + "description": "a POST request with one notification rule", "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/contacts/abc/media", + "path": "/contacts/abc/notification_rules", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "media": [ + "notification_rules": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } @@ -1480,88 +2035,92 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "abc_sms" + { + "json_class": "Pact::Term", + "data": { + "generate": "05983623-fcef-42da-af44-ed6990b500fa", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + } ] } }, { - "description": "a POST request with one medium", - "provider_state": "no contact exists", + "description": "a PATCH request for a single entity", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/contacts/abc/media", + "method": "patch", + "path": "/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "media": [ - { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 - } - ] - } + "body": [ + { + "op": "replace", + "path": "/entities/0/name", + "value": "example3.com" + } + ] }, "response": { - "status": 422, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { "errors": [ - "Contact id: 'abc' could not be loaded" + "could not find entity '1234'" ] } } }, { - "description": "a GET request for all media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a PATCH request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "patch", + "path": "/entities/1234", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/entities/0/name", + "value": "example3.com" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a GET request for a single entity", + "provider_state": "no entity exists", "request": { "method": "get", - "path": "/media" + "path": "/entities/1234" }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ - { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3, - "links": { - "contacts": [ - "abc" - ] - } - }, - { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, - "links": { - "contacts": [ - "abc" - ] - } - } + "errors": [ + "could not find entities: '1234'" ] } } }, { - "description": "a GET request for sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a GET request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "get", - "path": "/media/abc_sms" + "path": "/entities/1234" }, "response": { "status": 200, @@ -1569,47 +2128,40 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ + "entities": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, - "links": { - "contacts": [ - "abc" - ] - } + "name": "www.example.com", + "id": "1234" } ] } } }, { - "description": "a GET request for sms media", - "provider_state": "no contact exists", + "description": "a GET request for all entities", + "provider_state": "no entity exists", "request": { "method": "get", - "path": "/media/abc_sms" + "path": "/entities" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find contact 'abc'" + "entities": [ + ] } } }, { - "description": "a GET request for email and sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a GET request for all entities", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "get", - "path": "/media/abc_email,abc_sms" + "path": "/entities" }, "response": { "status": 200, @@ -1617,160 +2169,74 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ - { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3, - "links": { - "contacts": [ - "abc" - ] - } - }, + "entities": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, - "links": { - "contacts": [ - "abc" - ] - } + "name": "www.example.com", + "id": "1234" } ] } } }, { - "description": "a DELETE request for two media", - "provider_state": "a contact with id 'abc' has email and sms media", - "request": { - "method": "delete", - "path": "/media/abc_email,abc_sms", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for one medium", - "provider_state": "a contact with id 'abc' has email and sms media", - "request": { - "method": "delete", - "path": "/media/abc_email", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for one medium", - "provider_state": "no contact exists", + "description": "a POST request with two entities", + "provider_state": "no entity exists", "request": { - "method": "delete", - "path": "/media/abc_email", - "body": null - }, - "response": { - "status": 404, + "method": "post", + "path": "/entities", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find contact 'abc'" + "entities": [ + { + "name": "example.org", + "id": "57_example" + }, + { + "name": "example2.org", + "id": "58" + } ] } - } - }, - { - "description": "a PATCH request for email and sms media", - "provider_state": "a contact with id 'abc' has email and sms media", - "request": { - "method": "patch", - "path": "/media/abc_email,abc_sms", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/media/0/interval", - "value": 50 - }, - { - "op": "replace", - "path": "/media/0/rollup_threshold", - "value": 3 - } - ] }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for email media", - "provider_state": "a contact with id 'abc' has email and sms media", - "request": { - "method": "patch", - "path": "/media/abc_email", + "status": 201, "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - { - "op": "replace", - "path": "/media/0/interval", - "value": 50 - }, - { - "op": "replace", - "path": "/media/0/rollup_threshold", - "value": 3 - } + "57_example", + "58" ] - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a PATCH request for email media", - "provider_state": "no contact exists", + "description": "a POST request with one entity", + "provider_state": "no entity exists", "request": { - "method": "patch", - "path": "/media/abc_email", + "method": "post", + "path": "/entities", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/media/0/interval", - "value": 50 - } - ] + "body": { + "entities": [ + { + "name": "example.org", + "id": "57_example" + } + ] + } }, "response": { - "status": 404, + "status": 201, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": { - "errors": [ - "could not find contact 'abc'" - ] - } + "body": [ + "57_example" + ] } } ], diff --git a/spec/service_consumers/provider_states_for_flapjack-diner.rb b/spec/service_consumers/provider_states_for_flapjack-diner.rb index 6cb740f85..679241b6d 100644 --- a/spec/service_consumers/provider_states_for_flapjack-diner.rb +++ b/spec/service_consumers/provider_states_for_flapjack-diner.rb @@ -24,6 +24,14 @@ end end + provider_state "no notification rule exists" do + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end + provider_state "an entity 'www.example.com' with id '1234' exists" do set_up do redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') @@ -190,4 +198,91 @@ end end + provider_state "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists" do + set_up do + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + + contact_data = {'id' => 'abc', + 'first_name' => 'Jim', + 'last_name' => 'Smith', + 'email' => 'jims@example.com', + 'timezone' => 'UTC', + 'tags' => ['admin', 'night_shift']} + contact = Flapjack::Data::Contact.add(contact_data, :redis => redis) + existing_nr = contact.notification_rules.first + + nr_data = { + :id => '05983623-fcef-42da-af44-ed6990b500fa', + :tags => [], + :regex_tags => [], + :entities => [], + :regex_entities => [], + :time_restrictions => [], + :warning_media => ["email"], + :critical_media => ["sms", "email"], + :warning_blackhole => false, + :critical_blackhole => false + } + contact.add_notification_rule(nr_data) + contact.delete_notification_rule(existing_nr) + end + + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end + + provider_state "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists" do + set_up do + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + + contact_data = {'id' => 'abc', + 'first_name' => 'Jim', + 'last_name' => 'Smith', + 'email' => 'jims@example.com', + 'timezone' => 'UTC', + 'tags' => ['admin', 'night_shift']} + contact = Flapjack::Data::Contact.add(contact_data, :redis => redis) + existing_nr = contact.notification_rules.first + + nr_data = { + :id => '05983623-fcef-42da-af44-ed6990b500fa', + :tags => [], + :regex_tags => [], + :entities => [], + :regex_entities => [], + :time_restrictions => [], + :warning_media => ["email"], + :critical_media => ["sms", "email"], + :warning_blackhole => false, + :critical_blackhole => false + } + contact.add_notification_rule(nr_data) + + nr_data_2 = { + :id => '20f182fc-6e32-4794-9007-97366d162c51', + :tags => ['physical'], + :regex_tags => [], + :entities => ['example.com'], + :regex_entities => [], + :time_restrictions => [], + :warning_media => ["email"], + :critical_media => ["sms", "email"], + :warning_blackhole => true, + :critical_blackhole => true + } + contact.add_notification_rule(nr_data_2) + contact.delete_notification_rule(existing_nr) + end + + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end + + end \ No newline at end of file From 4dc429c5faa1f7fad0ef1e9fda643b9aa8e05b1e Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Thu, 25 Sep 2014 16:53:17 +0930 Subject: [PATCH 18/69] pact data for test_notifications --- .../pacts/flapjack-diner_v1.0.json | 2278 ++++++++++------- 1 file changed, 1314 insertions(+), 964 deletions(-) diff --git a/spec/service_consumers/pacts/flapjack-diner_v1.0.json b/spec/service_consumers/pacts/flapjack-diner_v1.0.json index e99b3d0ad..8cea4d49b 100644 --- a/spec/service_consumers/pacts/flapjack-diner_v1.0.json +++ b/spec/service_consumers/pacts/flapjack-diner_v1.0.json @@ -7,42 +7,21 @@ }, "interactions": [ { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no check exists", + "description": "a POST request with one test notification", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-25T15%3A46%3A26%2B09%3A30" - }, - "response": { - "status": 404, + "method": "post", + "path": "/test_notifications/entities/1234,5678", + "headers": { + "Content-Type": "application/vnd.api+json" + }, "body": { - "errors": [ - "could not find entity 'www.example.com'" + "test_notifications": [ + { + "summary": "testing" + } ] } - } - }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", - "query": "start_time=2014-09-25T15%3A46%3A26%2B09%3A30" - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-25T15%3A46%3A26%2B09%3A30" }, "response": { "status": 204, @@ -50,47 +29,21 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no check exists", + "description": "a POST request with one test notification", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "method": "post", + "path": "/test_notifications/entities/1234", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T15:46:26+09:30" - } - ] - }, - "response": { - "status": 404, "body": { - "errors": [ - "could not find entity 'www.example.com'" + "test_notifications": [ + { + "summary": "testing" + } ] } - } - }, - { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", - "request": { - "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T15:46:26+09:30" - } - ] }, "response": { "status": 204, @@ -98,45 +51,47 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one test notification", + "provider_state": "no entity exists", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "method": "post", + "path": "/test_notifications/entities/1234", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T15:46:26+09:30" - } - ] + "body": { + "test_notifications": [ + { + "summary": "testing" + } + ] + } }, "response": { - "status": 204, - "body": "" + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a POST request with two test notifications", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "path": "/test_notifications/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "test_notifications": [ { - "duration": 3600, - "summary": "working" + "summary": "testing" }, { - "duration": 3600, - "summary": "more work" + "summary": "more tests" } ] } @@ -147,23 +102,21 @@ } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with two test notifications", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/test_notifications/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "test_notifications": [ { - "duration": 3600, - "summary": "working" + "summary": "testing" }, { - "duration": 3600, - "summary": "more work" + "summary": "more tests" } ] } @@ -174,19 +127,18 @@ } }, { - "description": "a POST request with one unscheduled maintenance period", + "description": "a POST request with one test notification", "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "path": "/test_notifications/checks/www.example.com:SSH,www.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "test_notifications": [ { - "duration": 3600, - "summary": "working" + "summary": "testing" } ] } @@ -197,19 +149,18 @@ } }, { - "description": "a POST request with one unscheduled maintenance period", + "description": "a POST request with one test notification", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/test_notifications/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "test_notifications": [ { - "duration": 3600, - "summary": "working" + "summary": "testing" } ] } @@ -220,54 +171,47 @@ } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a POST request with one test notification", + "provider_state": "no check exists", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "path": "/test_notifications/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-25T15:46:26+09:30", - "duration": 3600, - "summary": "working" - }, + "test_notifications": [ { - "start_time": "2014-09-25T17:46:26+09:30", - "duration": 3600, - "summary": "more work" + "summary": "testing" } ] } }, "response": { - "status": 204, - "body": "" + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { - "description": "a POST request with two scheduled maintenance periods", + "description": "a POST request with two test notifications", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "path": "/test_notifications/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "test_notifications": [ { - "start_time": "2014-09-25T15:46:26+09:30", - "duration": 3600, - "summary": "working" + "summary": "testing" }, { - "start_time": "2014-09-25T17:46:26+09:30", - "duration": 3600, - "summary": "more work" + "summary": "more tests" } ] } @@ -278,44 +222,21 @@ } }, { - "description": "a POST request with one scheduled maintenance period", + "description": "a POST request with two test notifications", "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "path": "/test_notifications/checks/www.example.com:SSH,www.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "test_notifications": [ { - "start_time": "2014-09-25T15:46:26+09:30", - "duration": 3600, - "summary": "working" - } - ] - } - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "scheduled_maintenances": [ + "summary": "testing" + }, { - "start_time": "2014-09-25T15:46:26+09:30", - "duration": 3600, - "summary": "working" + "summary": "more tests" } ] } @@ -325,55 +246,12 @@ "body": "" } }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no entity exists", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-25T15%3A46%3A26%2B09%3A30" - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } - } - }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234,5678", - "query": "start_time=2014-09-25T15%3A46%3A26%2B09%3A30" - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-25T15%3A46%3A26%2B09%3A30" - }, - "response": { - "status": 204, - "body": "" - } - }, { "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no entity exists", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/json-patch+json" }, @@ -381,25 +259,21 @@ { "op": "replace", "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T15:46:26+09:30" + "value": "2014-09-25T16:51:48+09:30" } ] }, "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } + "status": 204, + "body": "" } }, { "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/entities/1234,5678", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, @@ -407,7 +281,7 @@ { "op": "replace", "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T15:46:26+09:30" + "value": "2014-09-25T16:51:48+09:30" } ] }, @@ -418,7 +292,7 @@ }, { "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "provider_state": "no entity exists", "request": { "method": "patch", "path": "/unscheduled_maintenances/entities/1234", @@ -429,33 +303,34 @@ { "op": "replace", "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T15:46:26+09:30" + "value": "2014-09-25T16:51:48+09:30" } ] }, "response": { - "status": 204, - "body": "" + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } } }, { - "description": "a POST request with two unscheduled maintenance periods", + "description": "a POST request with one scheduled maintenance period", "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "path": "/scheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "scheduled_maintenances": [ { + "start_time": "2014-09-25T16:51:48+09:30", "duration": 3600, "summary": "working" - }, - { - "duration": 3600, - "summary": "more work" } ] } @@ -466,23 +341,20 @@ } }, { - "description": "a POST request with two unscheduled maintenance periods", + "description": "a POST request with one scheduled maintenance period", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "path": "/scheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "scheduled_maintenances": [ { + "start_time": "2014-09-25T16:51:49+09:30", "duration": 3600, "summary": "working" - }, - { - "duration": 3600, - "summary": "more work" } ] } @@ -493,17 +365,18 @@ } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "no entity exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "path": "/scheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "scheduled_maintenances": [ { + "start_time": "2014-09-25T16:51:49+09:30", "duration": 3600, "summary": "working" } @@ -511,24 +384,34 @@ } }, "response": { - "status": 204, - "body": "" + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } } }, { - "description": "a POST request with one unscheduled maintenance period", + "description": "a POST request with two scheduled maintenance periods", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "path": "/scheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "scheduled_maintenances": [ { + "start_time": "2014-09-25T16:51:49+09:30", "duration": 3600, "summary": "working" + }, + { + "start_time": "2014-09-25T18:51:49+09:30", + "duration": 3600, + "summary": "more work" } ] } @@ -550,12 +433,12 @@ "body": { "scheduled_maintenances": [ { - "start_time": "2014-09-25T15:46:26+09:30", + "start_time": "2014-09-25T16:51:49+09:30", "duration": 3600, "summary": "working" }, { - "start_time": "2014-09-25T17:46:26+09:30", + "start_time": "2014-09-25T18:51:49+09:30", "duration": 3600, "summary": "more work" } @@ -568,25 +451,42 @@ } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "unscheduled_maintenances": [ { - "start_time": "2014-09-25T15:46:26+09:30", "duration": 3600, "summary": "working" - }, + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ { - "start_time": "2014-09-25T17:46:26+09:30", "duration": 3600, - "summary": "more work" + "summary": "working" } ] } @@ -597,20 +497,50 @@ } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "no entity exists", "request": { "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } + } + }, + { + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ { - "start_time": "2014-09-25T15:46:27+09:30", "duration": 3600, "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" } ] } @@ -621,20 +551,23 @@ } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "unscheduled_maintenances": [ { - "start_time": "2014-09-25T15:46:27+09:30", "duration": 3600, "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" } ] } @@ -645,48 +578,84 @@ } }, { - "description": "a PATCH request for a single check", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/entities/1234,5678", + "query": "start_time=2014-09-25T16%3A51%3A49%2B09%3A30" + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-25T16%3A51%3A49%2B09%3A30" + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", "provider_state": "no entity exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-25T16%3A51%3A49%2B09%3A30" + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { "method": "patch", - "path": "/checks/www.example.com:SSH", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/checks/0/enabled", - "value": false + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T16:51:49+09:30" } ] }, "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find entity 'www.example.com'" - ] - } + "status": 204, + "body": "" } }, { - "description": "a PATCH request for a single check", + "description": "a PATCH request for an unscheduled maintenance period", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "patch", - "path": "/checks/www.example.com:SSH", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/checks/0/enabled", - "value": false + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T16:51:49+09:30" } ] }, @@ -696,187 +665,182 @@ } }, { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "no entity exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no check exists", "request": { - "method": "get", - "path": "/checks/www.example.com:SSH" + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-25T16:51:49+09:30" + } + ] }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find entity checks: 'www.example.com:SSH'" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "get", - "path": "/checks/www.example.com:SSH" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "scheduled_maintenances": [ { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } + "start_time": "2014-09-25T16:51:49+09:30", + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for all checks", + "description": "a POST request with one scheduled maintenance period", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/checks" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "scheduled_maintenances": [ { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } + "start_time": "2014-09-25T16:51:49+09:30", + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for all checks", - "provider_state": "no entity exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "no check exists", "request": { - "method": "get", - "path": "/checks" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ - + "scheduled_maintenances": [ + { + "start_time": "2014-09-25T16:51:49+09:30", + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" ] } } }, { - "description": "a POST request with two checks", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "post", - "path": "/checks", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "scheduled_maintenances": [ { - "name": "SSH", - "entity_id": "1234" + "start_time": "2014-09-25T16:51:49+09:30", + "duration": 3600, + "summary": "working" }, { - "name": "PING", - "entity_id": "1234" + "start_time": "2014-09-25T18:51:49+09:30", + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "www.example.com:SSH", - "www.example.com:PING" - ] + "status": 204, + "body": "" } }, { - "description": "a POST request with one check", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { "method": "post", - "path": "/checks", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "scheduled_maintenances": [ { - "name": "PING", - "entity_id": "1234" + "start_time": "2014-09-25T16:51:49+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-25T18:51:49+09:30", + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "www.example.com:PING" - ] + "status": 204, + "body": "" } }, { - "description": "a DELETE request for a single contact", - "provider_state": "no contact exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null - }, - "response": { - "status": 404, + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find contacts 'abc'" + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } ] } - } - }, - { - "description": "a DELETE request for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", - "request": { - "method": "delete", - "path": "/contacts/abc,872", - "body": null }, "response": { "status": 204, @@ -884,12 +848,22 @@ } }, { - "description": "a DELETE request for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 204, @@ -897,50 +871,53 @@ } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "no contact exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "no check exists", "request": { - "method": "patch", - "path": "/contacts/323", + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find contacts '323'" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a PATCH requestto change a link for a single contact", - "provider_state": "a contact with id '872' exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/contacts/872", + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" - } - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } }, "response": { "status": 204, @@ -948,21 +925,26 @@ } }, { - "description": "a PATCH request to change links for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "patch", - "path": "/contacts/abc,872", + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" - } - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } }, "response": { "status": 204, @@ -970,21 +952,12 @@ } }, { - "description": "a PATCH request to change properties for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "patch", - "path": "/contacts/abc,872", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "query": "start_time=2014-09-25T16%3A51%3A49%2B09%3A30" }, "response": { "status": 204, @@ -992,21 +965,12 @@ } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/contacts/abc", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-25T16%3A51%3A49%2B09%3A30" }, "response": { "status": 204, @@ -1014,30 +978,28 @@ } }, { - "description": "a GET request for a single contact", - "provider_state": "no contact exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no check exists", "request": { - "method": "get", - "path": "/contacts/abc" + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-25T16%3A51%3A49%2B09%3A30" }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find contacts 'abc'" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a GET request for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a GET request for all entities", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "get", - "path": "/contacts/abc" + "path": "/entities" }, "response": { "status": 200, @@ -1045,28 +1007,21 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "contacts": [ + "entities": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "name": "www.example.com", + "id": "1234" } ] } } }, { - "description": "a GET request for all contacts", - "provider_state": "no contact exists", + "description": "a GET request for all entities", + "provider_state": "no entity exists", "request": { "method": "get", - "path": "/contacts" + "path": "/entities" }, "response": { "status": 200, @@ -1074,12 +1029,165 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "contacts": [ + "entities": [ ] } } }, + { + "description": "a GET request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "get", + "path": "/entities/1234" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "entities": [ + { + "name": "www.example.com", + "id": "1234" + } + ] + } + } + }, + { + "description": "a GET request for a single entity", + "provider_state": "no entity exists", + "request": { + "method": "get", + "path": "/entities/1234" + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entities: '1234'" + ] + } + } + }, + { + "description": "a POST request with one entity", + "provider_state": "no entity exists", + "request": { + "method": "post", + "path": "/entities", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "entities": [ + { + "name": "example.org", + "id": "57_example" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example" + ] + } + }, + { + "description": "a POST request with two entities", + "provider_state": "no entity exists", + "request": { + "method": "post", + "path": "/entities", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "entities": [ + { + "name": "example.org", + "id": "57_example" + }, + { + "name": "example2.org", + "id": "58" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example", + "58" + ] + } + }, + { + "description": "a PATCH request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "patch", + "path": "/entities/1234", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/entities/0/name", + "value": "example3.com" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for a single entity", + "provider_state": "no entity exists", + "request": { + "method": "patch", + "path": "/entities/1234", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/entities/0/name", + "value": "example3.com" + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } + } + }, { "description": "a GET request for all contacts", "provider_state": "a contact with id 'abc' exists", @@ -1110,13 +1218,35 @@ } }, { - "description": "a POST request with one contact", + "description": "a GET request for all contacts", + "provider_state": "no contact exists", + "request": { + "method": "get", + "path": "/contacts" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "contacts": [ + + ] + } + } + }, + { + "description": "a GET request for a single contact", "provider_state": "a contact with id 'abc' exists", "request": { - "method": "post", - "path": "/contacts", + "method": "get", + "path": "/contacts/abc" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { "contacts": [ @@ -1133,15 +1263,23 @@ } ] } + } + }, + { + "description": "a GET request for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "get", + "path": "/contacts/abc" }, "response": { - "status": 409, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { "errors": [ - "Contacts already exist with the following IDs: abc" + "could not find contacts 'abc'" ] } } @@ -1224,32 +1362,58 @@ } }, { - "description": "a DELETE request for one medium", - "provider_state": "no contact exists", + "description": "a POST request with one contact", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "delete", - "path": "/media/abc_email", - "body": null - }, - "response": { - "status": 404, + "method": "post", + "path": "/contacts", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find contact 'abc'" + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + } + ] + } + }, + "response": { + "status": 409, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "Contacts already exist with the following IDs: abc" ] } } }, { - "description": "a DELETE request for two media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a PATCH request to change properties for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { - "method": "delete", - "path": "/media/abc_email,abc_sms", - "body": null + "method": "patch", + "path": "/contacts/abc,872", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] }, "response": { "status": 204, @@ -1257,12 +1421,21 @@ } }, { - "description": "a DELETE request for one medium", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a PATCH request to change properties for a single contact", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "delete", - "path": "/media/abc_email", - "body": null + "method": "patch", + "path": "/contacts/abc", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] }, "response": { "status": 204, @@ -1270,19 +1443,19 @@ } }, { - "description": "a PATCH request for email media", + "description": "a PATCH request to change properties for a single contact", "provider_state": "no contact exists", "request": { "method": "patch", - "path": "/media/abc_email", + "path": "/contacts/323", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/media/0/interval", - "value": 50 + "path": "/contacts/0/timezone", + "value": "UTC" } ] }, @@ -1293,30 +1466,25 @@ }, "body": { "errors": [ - "could not find contact 'abc'" + "could not find contacts '323'" ] } } }, { - "description": "a PATCH request for email and sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a PATCH requestto change a link for a single contact", + "provider_state": "a contact with id '872' exists", "request": { "method": "patch", - "path": "/media/abc_email,abc_sms", + "path": "/contacts/872", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { - "op": "replace", - "path": "/media/0/interval", - "value": 50 - }, - { - "op": "replace", - "path": "/media/0/rollup_threshold", - "value": 3 + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" } ] }, @@ -1326,24 +1494,19 @@ } }, { - "description": "a PATCH request for email media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a PATCH request to change links for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { "method": "patch", - "path": "/media/abc_email", + "path": "/contacts/abc,872", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { - "op": "replace", - "path": "/media/0/interval", - "value": 50 - }, - { - "op": "replace", - "path": "/media/0/rollup_threshold", - "value": 3 + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" } ] }, @@ -1353,11 +1516,38 @@ } }, { - "description": "a GET request for sms media", + "description": "a DELETE request for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", + "request": { + "method": "delete", + "path": "/contacts/abc,872", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a single contact", "provider_state": "no contact exists", "request": { - "method": "get", - "path": "/media/abc_sms" + "method": "delete", + "path": "/contacts/abc", + "body": null }, "response": { "status": 404, @@ -1366,17 +1556,17 @@ }, "body": { "errors": [ - "could not find contact 'abc'" + "could not find contacts 'abc'" ] } } }, { - "description": "a GET request for email and sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a GET request for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { "method": "get", - "path": "/media/abc_email,abc_sms" + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" }, "response": { "status": 200, @@ -1384,39 +1574,44 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ - { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3, - "links": { - "contacts": [ - "abc" - ] - } - }, + "notification_rules": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, - "links": { - "contacts": [ - "abc" - ] - } + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } } }, { - "description": "a GET request for sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a GET request for all notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { "method": "get", - "path": "/media/abc_sms" + "path": "/notification_rules" }, "response": { "status": 200, @@ -1424,28 +1619,44 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ + "notification_rules": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, - "links": { - "contacts": [ - "abc" - ] - } + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } } }, { - "description": "a GET request for all media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a GET request for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { "method": "get", - "path": "/media" + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51" }, "response": { "status": 200, @@ -1453,87 +1664,129 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ - { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3, - "links": { - "contacts": [ - "abc" - ] - } - }, + "notification_rules": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, - "links": { - "contacts": [ - "abc" - ] - } + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + }, + { + "id": "20f182fc-6e32-4794-9007-97366d162c51", + "tags": [ + "physical" + ], + "regex_tags": [ + + ], + "entities": [ + "example.com" + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": true, + "critical_blackhole": true } ] } } }, { - "description": "a POST request with one medium", - "provider_state": "no contact exists", + "description": "a GET request for a single notification rule", + "provider_state": "no notification rule exists", "request": { - "method": "post", - "path": "/contacts/abc/media", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "media": [ - { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 - } - ] - } + "method": "get", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" }, "response": { - "status": 422, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { "errors": [ - "Contact id: 'abc' could not be loaded" + "could not find notification rules '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a POST request with two media", + "description": "a POST request with two notification rules", "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/contacts/abc/media", + "path": "/contacts/abc/notification_rules", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "media": [ + "notification_rules": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false }, { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3 + "entity_tags": null, + "entities": [ + "foo-app-02.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": true, + "critical_blackhole": false } ] } @@ -1544,27 +1797,52 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "abc_sms", - "abc_email" + { + "json_class": "Pact::Term", + "data": { + "generate": "05983623-fcef-42da-af44-ed6990b500fa", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + }, + { + "json_class": "Pact::Term", + "data": { + "generate": "20f182fc-6e32-4794-9007-97366d162c51", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + } ] } }, { - "description": "a POST request with one medium", + "description": "a POST request with one notification rule", "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/contacts/abc/media", + "path": "/contacts/abc/notification_rules", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "media": [ + "notification_rules": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } @@ -1575,17 +1853,48 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "abc_sms" + { + "json_class": "Pact::Term", + "data": { + "generate": "05983623-fcef-42da-af44-ed6990b500fa", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + } ] } }, { - "description": "a DELETE request for a single notification rule", - "provider_state": "no notification rule exists", + "description": "a POST request with one notification rule", + "provider_state": "no contact exists", "request": { - "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "body": null + "method": "post", + "path": "/contacts/abc/notification_rules", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "notification_rules": [ + { + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + } + ] + } }, "response": { "status": 404, @@ -1594,18 +1903,27 @@ }, "body": { "errors": [ - "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" + "could not find contact 'abc'" ] } } }, { - "description": "a DELETE request for two notification rules", + "description": "a PATCH request to change properties for two notification rules", "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { - "method": "delete", + "method": "patch", "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", - "body": null + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] }, "response": { "status": 204, @@ -1613,12 +1931,21 @@ } }, { - "description": "a DELETE request for a single notification rule", + "description": "a PATCH request to change properties for a single notification rule", "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "delete", + "method": "patch", "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "body": null + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] }, "response": { "status": 204, @@ -1655,21 +1982,12 @@ } }, { - "description": "a PATCH request to change properties for two notification rules", + "description": "a DELETE request for two notification rules", "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { - "method": "patch", + "method": "delete", "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false - } - ] + "body": null }, "response": { "status": 204, @@ -1677,21 +1995,12 @@ } }, { - "description": "a PATCH request to change properties for a single notification rule", + "description": "a DELETE request for a single notification rule", "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "patch", + "method": "delete", "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false - } - ] + "body": null }, "response": { "status": 204, @@ -1699,11 +2008,12 @@ } }, { - "description": "a GET request for a single notification rule", + "description": "a DELETE request for a single notification rule", "provider_state": "no notification rule exists", "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "body": null }, "response": { "status": 404, @@ -1712,17 +2022,17 @@ }, "body": { "errors": [ - "could not find notification rules '05983623-fcef-42da-af44-ed6990b500fa'" + "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a GET request for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", + "description": "a GET request for all checks", + "provider_state": "no entity exists", "request": { "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51" + "path": "/checks" }, "response": { "status": 200, @@ -1730,71 +2040,18 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "notification_rules": [ - { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - }, - { - "id": "20f182fc-6e32-4794-9007-97366d162c51", - "tags": [ - "physical" - ], - "regex_tags": [ - - ], - "entities": [ - "example.com" - ], - "regex_entities": [ - - ], - "time_restrictions": [ + "checks": [ - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": true, - "critical_blackhole": true - } ] } } }, { - "description": "a GET request for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "description": "a GET request for all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" + "path": "/checks" }, "response": { "status": 200, @@ -1802,44 +2059,27 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "notification_rules": [ + "checks": [ { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } } ] } } }, { - "description": "a GET request for all notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/notification_rules" + "path": "/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -1847,70 +2087,27 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "notification_rules": [ + "checks": [ { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } } ] } } }, { - "description": "a POST request with one notification rule", - "provider_state": "no contact exists", + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/contacts/abc/notification_rules", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "notification_rules": [ - { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - } - ] - } + "method": "get", + "path": "/checks/www.example.com:SSH" }, "response": { "status": 404, @@ -1919,56 +2116,25 @@ }, "body": { "errors": [ - "could not find contact 'abc'" + "could not find entity checks: 'www.example.com:SSH'" ] } } }, { - "description": "a POST request with two notification rules", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with one check", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/contacts/abc/notification_rules", + "path": "/checks", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "notification_rules": [ - { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - }, + "checks": [ { - "entity_tags": null, - "entities": [ - "foo-app-02.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": true, - "critical_blackhole": false + "name": "PING", + "entity_id": "1234" } ] } @@ -1979,52 +2145,28 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - { - "json_class": "Pact::Term", - "data": { - "generate": "05983623-fcef-42da-af44-ed6990b500fa", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - }, - { - "json_class": "Pact::Term", - "data": { - "generate": "20f182fc-6e32-4794-9007-97366d162c51", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - } + "www.example.com:PING" ] } }, { - "description": "a POST request with one notification rule", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with two checks", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/contacts/abc/notification_rules", + "path": "/checks", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "notification_rules": [ + "checks": [ { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "name": "SSH", + "entity_id": "1234" + }, + { + "name": "PING", + "entity_id": "1234" } ] } @@ -2035,92 +2177,97 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - { - "json_class": "Pact::Term", - "data": { - "generate": "05983623-fcef-42da-af44-ed6990b500fa", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - } + "www.example.com:SSH", + "www.example.com:PING" ] } }, { - "description": "a PATCH request for a single entity", - "provider_state": "no entity exists", + "description": "a PATCH request for a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "patch", - "path": "/entities/1234", + "path": "/checks/www.example.com:SSH", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" + "path": "/checks/0/enabled", + "value": false } ] }, "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } + "status": 204, + "body": "" } }, { - "description": "a PATCH request for a single entity", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a PATCH request for a single check", + "provider_state": "no entity exists", "request": { "method": "patch", - "path": "/entities/1234", + "path": "/checks/www.example.com:SSH", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" + "path": "/checks/0/enabled", + "value": false } ] }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { - "description": "a GET request for a single entity", - "provider_state": "no entity exists", + "description": "a GET request for sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "get", - "path": "/entities/1234" + "path": "/media/abc_sms" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find entities: '1234'" + "media": [ + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } + } ] } } }, { - "description": "a GET request for a single entity", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for all media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "get", - "path": "/entities/1234" + "path": "/media" }, "response": { "status": 200, @@ -2128,21 +2275,39 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "entities": [ + "media": [ { - "name": "www.example.com", - "id": "1234" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3, + "links": { + "contacts": [ + "abc" + ] + } + }, + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } } ] } } }, { - "description": "a GET request for all entities", - "provider_state": "no entity exists", + "description": "a GET request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "get", - "path": "/entities" + "path": "/media/abc_email,abc_sms" }, "response": { "status": 200, @@ -2150,52 +2315,74 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "entities": [ - + "media": [ + { + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3, + "links": { + "contacts": [ + "abc" + ] + } + }, + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } + } ] } } }, { - "description": "a GET request for all entities", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for sms media", + "provider_state": "no contact exists", "request": { "method": "get", - "path": "/entities" + "path": "/media/abc_sms" }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "entities": [ - { - "name": "www.example.com", - "id": "1234" - } + "errors": [ + "could not find contact 'abc'" ] } } }, { - "description": "a POST request with two entities", - "provider_state": "no entity exists", + "description": "a POST request with two media", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/entities", + "path": "/contacts/abc/media", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "media": [ { - "name": "example.org", - "id": "57_example" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 }, { - "name": "example2.org", - "id": "58" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3 } ] } @@ -2206,25 +2393,27 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "57_example", - "58" + "abc_sms", + "abc_email" ] } }, { - "description": "a POST request with one entity", - "provider_state": "no entity exists", + "description": "a POST request with one medium", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/entities", + "path": "/contacts/abc/media", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "media": [ { - "name": "example.org", - "id": "57_example" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 } ] } @@ -2235,8 +2424,169 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "57_example" + "abc_sms" + ] + } + }, + { + "description": "a POST request with one medium", + "provider_state": "no contact exists", + "request": { + "method": "post", + "path": "/contacts/abc/media", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "media": [ + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 + } + ] + } + }, + "response": { + "status": 422, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "Contact id: 'abc' could not be loaded" + ] + } + } + }, + { + "description": "a PATCH request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", + "request": { + "method": "patch", + "path": "/media/abc_email,abc_sms", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/media/0/interval", + "value": 50 + }, + { + "op": "replace", + "path": "/media/0/rollup_threshold", + "value": 3 + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for email media", + "provider_state": "a contact with id 'abc' has email and sms media", + "request": { + "method": "patch", + "path": "/media/abc_email", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/media/0/interval", + "value": 50 + }, + { + "op": "replace", + "path": "/media/0/rollup_threshold", + "value": 3 + } ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for email media", + "provider_state": "no contact exists", + "request": { + "method": "patch", + "path": "/media/abc_email", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/media/0/interval", + "value": 50 + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contact 'abc'" + ] + } + } + }, + { + "description": "a DELETE request for two media", + "provider_state": "a contact with id 'abc' has email and sms media", + "request": { + "method": "delete", + "path": "/media/abc_email,abc_sms", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for one medium", + "provider_state": "a contact with id 'abc' has email and sms media", + "request": { + "method": "delete", + "path": "/media/abc_email", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for one medium", + "provider_state": "no contact exists", + "request": { + "method": "delete", + "path": "/media/abc_email", + "body": null + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contact 'abc'" + ] + } } } ], From 5139f29605079108d861480c4ad945a04889eb5e Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 26 Sep 2014 09:54:06 +0930 Subject: [PATCH 19/69] pagerduty_credentials pacts --- .../jsonapi/pagerduty_credential_methods.rb | 2 +- .../pacts/flapjack-diner_v1.0.json | 2990 +++++++++-------- .../provider_states_for_flapjack-diner.rb | 67 +- 3 files changed, 1701 insertions(+), 1358 deletions(-) diff --git a/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb b/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb index 1f253c6f8..bd6ea17a1 100644 --- a/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb +++ b/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb @@ -46,7 +46,7 @@ def self.registered(app) contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis) if contact.nil? semaphore.release - halt err(422, "Contact id '#{params[:contact_id]}' could not be loaded") + halt err(422, "Contact id: '#{params[:contact_id]}' could not be loaded") end pagerduty_credential_data = fields.inject({}) do |memo, field| diff --git a/spec/service_consumers/pacts/flapjack-diner_v1.0.json b/spec/service_consumers/pacts/flapjack-diner_v1.0.json index 8cea4d49b..a45d2a991 100644 --- a/spec/service_consumers/pacts/flapjack-diner_v1.0.json +++ b/spec/service_consumers/pacts/flapjack-diner_v1.0.json @@ -7,119 +7,125 @@ }, "interactions": [ { - "description": "a POST request with one test notification", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a POST request with one medium", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/test_notifications/entities/1234,5678", + "path": "/contacts/abc/media", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "test_notifications": [ + "media": [ { - "summary": "testing" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 } ] } }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one test notification", - "provider_state": "an entity 'www.example.com' with id '1234' exists", - "request": { - "method": "post", - "path": "/test_notifications/entities/1234", + "status": 201, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": { - "test_notifications": [ - { - "summary": "testing" - } - ] - } - }, - "response": { - "status": 204, - "body": "" + "body": [ + "abc_sms" + ] } }, { - "description": "a POST request with one test notification", - "provider_state": "no entity exists", + "description": "a POST request with one medium", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/test_notifications/entities/1234", + "path": "/contacts/abc/media", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "test_notifications": [ + "media": [ { - "summary": "testing" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 } ] } }, "response": { - "status": 404, + "status": 422, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity '1234'" + "Contact id: 'abc' could not be loaded" ] } } }, { - "description": "a POST request with two test notifications", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with two media", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/test_notifications/entities/1234", + "path": "/contacts/abc/media", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "test_notifications": [ + "media": [ { - "summary": "testing" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 }, { - "summary": "more tests" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3 } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc_sms", + "abc_email" + ] } }, { - "description": "a POST request with two test notifications", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a PATCH request for email media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/test_notifications/entities/1234,5678", + "method": "patch", + "path": "/media/abc_email", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "test_notifications": [ - { - "summary": "testing" - }, - { - "summary": "more tests" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/media/0/interval", + "value": 50 + }, + { + "op": "replace", + "path": "/media/0/rollup_threshold", + "value": 3 + } + ] }, "response": { "status": 204, @@ -127,21 +133,55 @@ } }, { - "description": "a POST request with one test notification", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a PATCH request for email media", + "provider_state": "no contact exists", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH,www.example.com:PING", + "method": "patch", + "path": "/media/abc_email", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/media/0/interval", + "value": 50 + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ - { - "summary": "testing" - } + "errors": [ + "could not find contact 'abc'" ] } + } + }, + { + "description": "a PATCH request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", + "request": { + "method": "patch", + "path": "/media/abc_email,abc_sms", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/media/0/interval", + "value": 50 + }, + { + "op": "replace", + "path": "/media/0/rollup_threshold", + "value": 3 + } + ] }, "response": { "status": 204, @@ -149,21 +189,12 @@ } }, { - "description": "a POST request with one test notification", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for one medium", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "test_notifications": [ - { - "summary": "testing" - } - ] - } + "method": "delete", + "path": "/media/abc_email", + "body": null }, "response": { "status": 204, @@ -171,50 +202,32 @@ } }, { - "description": "a POST request with one test notification", - "provider_state": "no check exists", + "description": "a DELETE request for one medium", + "provider_state": "no contact exists", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "test_notifications": [ - { - "summary": "testing" - } - ] - } + "method": "delete", + "path": "/media/abc_email", + "body": null }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find contact 'abc'" ] } } }, { - "description": "a POST request with two test notifications", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for two media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "test_notifications": [ - { - "summary": "testing" - }, - { - "summary": "more tests" - } - ] - } + "method": "delete", + "path": "/media/abc_email,abc_sms", + "body": null }, "response": { "status": 204, @@ -222,199 +235,210 @@ } }, { - "description": "a POST request with two test notifications", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a GET request for all media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH,www.example.com:PING", + "method": "get", + "path": "/media" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ - { - "summary": "testing" - }, + "media": [ { - "summary": "more tests" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3, + "links": { + "contacts": [ + "abc" + ] + } + }, + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/entities/1234,5678", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T16:51:48+09:30" - } - ] + "method": "get", + "path": "/media/abc_email,abc_sms" }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", - "request": { - "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", + "status": 200, "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T16:51:48+09:30" - } - ] - }, - "response": { - "status": 204, - "body": "" + "body": { + "media": [ + { + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3, + "links": { + "contacts": [ + "abc" + ] + } + }, + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } + } + ] + } } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no entity exists", + "description": "a GET request for sms media", + "provider_state": "no contact exists", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T16:51:48+09:30" - } - ] + "method": "get", + "path": "/media/abc_sms" }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity '1234'" + "could not find contact 'abc'" ] } } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "method": "get", + "path": "/media/abc_sms" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "media": [ { - "start_time": "2014-09-25T16:51:48+09:30", - "duration": 3600, - "summary": "working" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with one entity", + "provider_state": "no entity exists", "request": { "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "path": "/entities", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "entities": [ { - "start_time": "2014-09-25T16:51:49+09:30", - "duration": 3600, - "summary": "working" + "name": "example.org", + "id": "57_example" } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example" + ] } }, { - "description": "a POST request with one scheduled maintenance period", + "description": "a POST request with two entities", "provider_state": "no entity exists", "request": { "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "path": "/entities", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "entities": [ { - "start_time": "2014-09-25T16:51:49+09:30", - "duration": 3600, - "summary": "working" + "name": "example.org", + "id": "57_example" + }, + { + "name": "example2.org", + "id": "58" } ] } }, "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example", + "58" + ] } }, { - "description": "a POST request with two scheduled maintenance periods", + "description": "a PATCH request for a single entity", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "method": "patch", + "path": "/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-25T16:51:49+09:30", - "duration": 3600, - "summary": "working" - }, - { - "start_time": "2014-09-25T18:51:49+09:30", - "duration": 3600, - "summary": "more work" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/entities/0/name", + "value": "example3.com" + } + ] }, "response": { "status": 204, @@ -422,181 +446,246 @@ } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a PATCH request for a single entity", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "method": "patch", + "path": "/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/entities/0/name", + "value": "example3.com" + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-25T16:51:49+09:30", - "duration": 3600, - "summary": "working" - }, - { - "start_time": "2014-09-25T18:51:49+09:30", - "duration": 3600, - "summary": "more work" - } + "errors": [ + "could not find entity '1234'" ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for all entities", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "method": "get", + "path": "/entities" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "entities": [ { - "duration": 3600, - "summary": "working" + "name": "www.example.com", + "id": "1234" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for all entities", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "method": "get", + "path": "/entities" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } + "entities": [ + ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "no entity exists", + "description": "a GET request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "method": "get", + "path": "/entities/1234" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "entities": [ { - "duration": 3600, - "summary": "working" + "name": "www.example.com", + "id": "1234" } ] } + } + }, + { + "description": "a GET request for a single entity", + "provider_state": "no entity exists", + "request": { + "method": "get", + "path": "/entities/1234" }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity '1234'" + "could not find entities: '1234'" ] } } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with one contact", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "path": "/contacts", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, + "contacts": [ { - "duration": 3600, - "summary": "more work" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc" + ] } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a POST request with one contact", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "path": "/contacts", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, + "contacts": [ { - "duration": 3600, - "summary": "more work" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] } ] } }, "response": { - "status": 204, - "body": "" + "status": 409, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "Contacts already exist with the following IDs: abc" + ] + } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a POST request with two contacts", + "provider_state": "no contact exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234,5678", - "query": "start_time=2014-09-25T16%3A51%3A49%2B09%3A30" + "method": "post", + "path": "/contacts", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + }, + { + "id": "def", + "first_name": "Joan", + "last_name": "Smith", + "email": "joans@example.com" + } + ] + } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc", + "def" + ] } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a PATCH request to change properties for a single contact", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-25T16%3A51%3A49%2B09%3A30" + "method": "patch", + "path": "/contacts/abc", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] }, "response": { "status": 204, @@ -604,36 +693,19 @@ } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no entity exists", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-25T16%3A51%3A49%2B09%3A30" - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } - } - }, - { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a PATCH requestto change a link for a single contact", + "provider_state": "a contact with id '872' exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "path": "/contacts/872", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T16:51:49+09:30" + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" } ] }, @@ -643,19 +715,19 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request to change links for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/contacts/abc,872", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T16:51:49+09:30" + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" } ] }, @@ -665,49 +737,50 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no check exists", + "description": "a PATCH request to change properties for a single contact", + "provider_state": "no contact exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/contacts/323", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-25T16:51:49+09:30" + "path": "/contacts/0/timezone", + "value": "UTC" } ] }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find contacts '323'" ] } } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a PATCH request to change properties for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "method": "patch", + "path": "/contacts/abc,872", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-25T16:51:49+09:30", - "duration": 3600, - "summary": "working" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] }, "response": { "status": 204, @@ -715,23 +788,12 @@ } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for a single contact", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-25T16:51:49+09:30", - "duration": 3600, - "summary": "working" - } - ] - } + "method": "delete", + "path": "/contacts/abc", + "body": null }, "response": { "status": 204, @@ -739,56 +801,32 @@ } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "no check exists", + "description": "a DELETE request for a single contact", + "provider_state": "no contact exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-25T16:51:49+09:30", - "duration": 3600, - "summary": "working" - } - ] - } + "method": "delete", + "path": "/contacts/abc", + "body": null }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find contacts 'abc'" ] } } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-25T16:51:49+09:30", - "duration": 3600, - "summary": "working" - }, - { - "start_time": "2014-09-25T18:51:49+09:30", - "duration": 3600, - "summary": "more work" - } - ] - } + "method": "delete", + "path": "/contacts/abc,872", + "body": null }, "response": { "status": 204, @@ -796,181 +834,178 @@ } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a GET request for all contacts", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "method": "get", + "path": "/contacts" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-25T16:51:49+09:30", - "duration": 3600, - "summary": "working" - }, + "contacts": [ { - "start_time": "2014-09-25T18:51:49+09:30", - "duration": 3600, - "summary": "more work" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a GET request for all contacts", + "provider_state": "no contact exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "method": "get", + "path": "/contacts" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } + "contacts": [ + ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a single contact", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/contacts/abc" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "contacts": [ { - "duration": 3600, - "summary": "working" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "no check exists", + "description": "a GET request for a single contact", + "provider_state": "no contact exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } - ] - } + "method": "get", + "path": "/contacts/abc" }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find contacts 'abc'" ] } } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one check", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/checks", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, + "checks": [ { - "duration": 3600, - "summary": "more work" + "name": "PING", + "entity_id": "1234" } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:PING" + ] } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a POST request with two checks", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "path": "/checks", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "checks": [ { - "duration": 3600, - "summary": "working" + "name": "SSH", + "entity_id": "1234" }, { - "duration": 3600, - "summary": "more work" + "name": "PING", + "entity_id": "1234" } ] } }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", - "query": "start_time=2014-09-25T16%3A51%3A49%2B09%3A30" - }, - "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:SSH", + "www.example.com:PING" + ] } }, { - "description": "a DELETE request for a scheduled maintenance period", + "description": "a PATCH request for a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-25T16%3A51%3A49%2B09%3A30" + "method": "patch", + "path": "/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/checks/0/enabled", + "value": false + } + ] }, "response": { "status": 204, @@ -978,15 +1013,27 @@ } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no check exists", + "description": "a PATCH request for a single check", + "provider_state": "no entity exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-25T16%3A51%3A49%2B09%3A30" + "method": "patch", + "path": "/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/checks/0/enabled", + "value": false + } + ] }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ "could not find entity 'www.example.com'" @@ -995,11 +1042,11 @@ } }, { - "description": "a GET request for all entities", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for all checks", + "provider_state": "no entity exists", "request": { "method": "get", - "path": "/entities" + "path": "/checks" }, "response": { "status": 200, @@ -1007,21 +1054,18 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "entities": [ - { - "name": "www.example.com", - "id": "1234" - } + "checks": [ + ] } } }, { - "description": "a GET request for all entities", - "provider_state": "no entity exists", + "description": "a GET request for all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/entities" + "path": "/checks" }, "response": { "status": 200, @@ -1029,18 +1073,27 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "entities": [ - + "checks": [ + { + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } + } ] } } }, { - "description": "a GET request for a single entity", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/entities/1234" + "path": "/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -1048,21 +1101,27 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "entities": [ + "checks": [ { - "name": "www.example.com", - "id": "1234" + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } } ] } } }, { - "description": "a GET request for a single entity", + "description": "a GET request for check 'www.example.com:SSH'", "provider_state": "no entity exists", "request": { "method": "get", - "path": "/entities/1234" + "path": "/checks/www.example.com:SSH" }, "response": { "status": 404, @@ -1071,88 +1130,77 @@ }, "body": { "errors": [ - "could not find entities: '1234'" + "could not find entity checks: 'www.example.com:SSH'" ] } } }, { - "description": "a POST request with one entity", - "provider_state": "no entity exists", + "description": "a POST request with one test notification", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/entities", + "path": "/test_notifications/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "test_notifications": [ { - "name": "example.org", - "id": "57_example" + "summary": "testing" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "57_example" - ] + "status": 204, + "body": "" } }, { - "description": "a POST request with two entities", - "provider_state": "no entity exists", + "description": "a POST request with two test notifications", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/entities", + "path": "/test_notifications/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "test_notifications": [ { - "name": "example.org", - "id": "57_example" + "summary": "testing" }, { - "name": "example2.org", - "id": "58" + "summary": "more tests" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "57_example", - "58" - ] + "status": 204, + "body": "" } }, { - "description": "a PATCH request for a single entity", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with two test notifications", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "patch", - "path": "/entities/1234", + "method": "post", + "path": "/test_notifications/entities/1234,5678", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" - } - ] + "body": { + "test_notifications": [ + { + "summary": "testing" + }, + { + "summary": "more tests" + } + ] + } }, "response": { "status": 204, @@ -1160,27 +1208,24 @@ } }, { - "description": "a PATCH request for a single entity", + "description": "a POST request with one test notification", "provider_state": "no entity exists", "request": { - "method": "patch", - "path": "/entities/1234", + "method": "post", + "path": "/test_notifications/entities/1234", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" - } - ] + "body": { + "test_notifications": [ + { + "summary": "testing" + } + ] + } }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ "could not find entity '1234'" @@ -1189,231 +1234,194 @@ } }, { - "description": "a GET request for all contacts", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with one test notification", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/contacts" - }, - "response": { - "status": 200, + "method": "post", + "path": "/test_notifications/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "test_notifications": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "summary": "testing" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for all contacts", - "provider_state": "no contact exists", + "description": "a POST request with one test notification", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/contacts" - }, - "response": { - "status": 200, + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ - + "test_notifications": [ + { + "summary": "testing" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with two test notifications", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/contacts/abc" - }, - "response": { - "status": 200, + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "test_notifications": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "summary": "testing" + }, + { + "summary": "more tests" } ] } - } - }, - { - "description": "a GET request for a single contact", - "provider_state": "no contact exists", - "request": { - "method": "get", - "path": "/contacts/abc" }, "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find contacts 'abc'" - ] - } + "status": 204, + "body": "" } }, { - "description": "a POST request with two contacts", - "provider_state": "no contact exists", + "description": "a POST request with two test notifications", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { "method": "post", - "path": "/contacts", + "path": "/test_notifications/checks/www.example.com:SSH,www.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "test_notifications": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "summary": "testing" }, { - "id": "def", - "first_name": "Joan", - "last_name": "Smith", - "email": "joans@example.com" + "summary": "more tests" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "abc", - "def" - ] + "status": 204, + "body": "" } }, { - "description": "a POST request with one contact", - "provider_state": "no contact exists", + "description": "a POST request with one test notification", + "provider_state": "no check exists", "request": { "method": "post", - "path": "/contacts", + "path": "/test_notifications/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "test_notifications": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "summary": "testing" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "abc" - ] + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { - "description": "a POST request with one contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with one test notification", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { "method": "post", - "path": "/contacts", + "path": "/test_notifications/checks/www.example.com:SSH,www.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "test_notifications": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "summary": "testing" } ] } }, "response": { - "status": 409, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "Contacts already exist with the following IDs: abc" + "scheduled_maintenances": [ + { + "start_time": "2014-09-26T09:53:06+09:30", + "duration": 3600, + "summary": "working" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a PATCH request to change properties for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "patch", - "path": "/contacts/abc,872", + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-26T09:53:07+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-26T11:53:07+09:30", + "duration": 3600, + "summary": "more work" + } + ] + } }, "response": { "status": 204, @@ -1421,21 +1429,28 @@ } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "patch", - "path": "/contacts/abc", + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-26T09:53:07+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-26T11:53:07+09:30", + "duration": 3600, + "summary": "more work" + } + ] + } }, "response": { "status": 204, @@ -1443,50 +1458,51 @@ } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "no contact exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "no entity exists", "request": { - "method": "patch", - "path": "/contacts/323", + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-26T09:53:07+09:30", + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find contacts '323'" + "could not find entity '1234'" ] } } }, { - "description": "a PATCH requestto change a link for a single contact", - "provider_state": "a contact with id '872' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "patch", - "path": "/contacts/872", + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" - } - ] + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-26T09:53:07+09:30", + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 204, @@ -1494,21 +1510,22 @@ } }, { - "description": "a PATCH request to change links for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "patch", - "path": "/contacts/abc,872", + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" - } - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 204, @@ -1516,12 +1533,26 @@ } }, { - "description": "a DELETE request for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "delete", - "path": "/contacts/abc,872", - "body": null + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } }, "response": { "status": 204, @@ -1529,12 +1560,26 @@ } }, { - "description": "a DELETE request for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null + "method": "post", + "path": "/unscheduled_maintenances/entities/1234,5678", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } }, "response": { "status": 204, @@ -1542,388 +1587,346 @@ } }, { - "description": "a DELETE request for a single contact", - "provider_state": "no contact exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "no entity exists", "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find contacts 'abc'" + "could not find entity '1234'" ] } } }, { - "description": "a GET request for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "notification_rules": [ + "unscheduled_maintenances": [ { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for all notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/notification_rules" + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-26T09%3A53%3A07%2B09%3A30" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no entity exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-26T09%3A53%3A07%2B09%3A30" + }, + "response": { + "status": 404, "body": { - "notification_rules": [ - { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - } + "errors": [ + "could not find entity '1234'" ] } } }, { - "description": "a GET request for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51" + "method": "delete", + "path": "/scheduled_maintenances/entities/1234,5678", + "query": "start_time=2014-09-26T09%3A53%3A07%2B09%3A30" }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, - "body": { - "notification_rules": [ - { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - }, - { - "id": "20f182fc-6e32-4794-9007-97366d162c51", - "tags": [ - "physical" - ], - "regex_tags": [ - - ], - "entities": [ - "example.com" - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": true, - "critical_blackhole": true - } + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T09:53:07+09:30" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no entity exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T09:53:07+09:30" + } + ] + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" ] } } }, { - "description": "a GET request for a single notification rule", - "provider_state": "no notification rule exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" + "method": "patch", + "path": "/unscheduled_maintenances/entities/1234,5678", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T09:53:07+09:30" + } + ] }, "response": { - "status": 404, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find notification rules '05983623-fcef-42da-af44-ed6990b500fa'" + "scheduled_maintenances": [ + { + "start_time": "2014-09-26T09:53:07+09:30", + "duration": 3600, + "summary": "working" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a POST request with two notification rules", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "post", - "path": "/contacts/abc/notification_rules", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "notification_rules": [ + "scheduled_maintenances": [ { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "start_time": "2014-09-26T09:53:07+09:30", + "duration": 3600, + "summary": "working" }, { - "entity_tags": null, - "entities": [ - "foo-app-02.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": true, - "critical_blackhole": false + "start_time": "2014-09-26T11:53:07+09:30", + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - { - "json_class": "Pact::Term", - "data": { - "generate": "05983623-fcef-42da-af44-ed6990b500fa", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - }, - { - "json_class": "Pact::Term", - "data": { - "generate": "20f182fc-6e32-4794-9007-97366d162c51", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - } - ] + "status": 204, + "body": "" } }, { - "description": "a POST request with one notification rule", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { "method": "post", - "path": "/contacts/abc/notification_rules", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "notification_rules": [ + "scheduled_maintenances": [ { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "start_time": "2014-09-26T09:53:07+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-26T11:53:07+09:30", + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 201, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "no check exists", + "request": { + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "json_class": "Pact::Term", - "data": { - "generate": "05983623-fcef-42da-af44-ed6990b500fa", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-26T09:53:07+09:30", + "duration": 3600, + "summary": "working" } - } - ] + ] + } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { - "description": "a POST request with one notification rule", - "provider_state": "no contact exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { "method": "post", - "path": "/contacts/abc/notification_rules", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "notification_rules": [ + "scheduled_maintenances": [ { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "start_time": "2014-09-26T09:53:07+09:30", + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 404, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find contact 'abc'" + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a PATCH request to change properties for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false - } - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } }, "response": { "status": 204, @@ -1931,21 +1934,26 @@ } }, { - "description": "a PATCH request to change properties for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false - } - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } }, "response": { "status": 204, @@ -1953,41 +1961,49 @@ } }, { - "description": "a PATCH request to change properties for a single notification rule", - "provider_state": "no notification rule exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "no check exists", "request": { - "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false - } - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a DELETE request for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", - "body": null + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 204, @@ -1995,12 +2011,12 @@ } }, { - "description": "a DELETE request for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "body": null + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-26T09%3A53%3A07%2B09%3A30" }, "response": { "status": 204, @@ -2008,165 +2024,244 @@ } }, { - "description": "a DELETE request for a single notification rule", - "provider_state": "no notification rule exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no check exists", "request": { "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "body": null + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-26T09%3A53%3A07%2B09%3A30" }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a GET request for all checks", - "provider_state": "no entity exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "get", - "path": "/checks" + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "query": "start_time=2014-09-26T09%3A53%3A07%2B09%3A30" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "checks": [ - - ] - } + "status": 204, + "body": "" } }, { - "description": "a GET request for all checks", + "description": "a PATCH request for an unscheduled maintenance period", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/checks" + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T09:53:07+09:30" + } + ] }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no check exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T09:53:07+09:30" + } + ] + }, + "response": { + "status": 404, "body": { - "checks": [ - { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } - } + "errors": [ + "could not find entity 'www.example.com'" ] } } }, { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", "request": { - "method": "get", - "path": "/checks/www.example.com:SSH" + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T09:53:07+09:30" + } + ] }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one notification rule", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "post", + "path": "/contacts/abc/notification_rules", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "notification_rules": [ { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } - } - }, - { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "no entity exists", - "request": { - "method": "get", - "path": "/checks/www.example.com:SSH" }, "response": { - "status": 404, + "status": 201, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": { - "errors": [ - "could not find entity checks: 'www.example.com:SSH'" - ] - } + "body": [ + { + "json_class": "Pact::Term", + "data": { + "generate": "05983623-fcef-42da-af44-ed6990b500fa", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + } + ] } }, { - "description": "a POST request with one check", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with one notification rule", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/checks", + "path": "/contacts/abc/notification_rules", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "notification_rules": [ { - "name": "PING", - "entity_id": "1234" + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } }, "response": { - "status": 201, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - "www.example.com:PING" - ] + "body": { + "errors": [ + "could not find contact 'abc'" + ] + } } }, { - "description": "a POST request with two checks", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with two notification rules", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/checks", + "path": "/contacts/abc/notification_rules", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "notification_rules": [ { - "name": "SSH", - "entity_id": "1234" + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false }, { - "name": "PING", - "entity_id": "1234" + "entity_tags": null, + "entities": [ + "foo-app-02.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": true, + "critical_blackhole": false } ] } @@ -2177,24 +2272,36 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "www.example.com:SSH", - "www.example.com:PING" + { + "json_class": "Pact::Term", + "data": { + "generate": "05983623-fcef-42da-af44-ed6990b500fa", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + }, + { + "json_class": "Pact::Term", + "data": { + "generate": "20f182fc-6e32-4794-9007-97366d162c51", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + } ] } }, { - "description": "a PATCH request for a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request to change properties for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { "method": "patch", - "path": "/checks/www.example.com:SSH", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/checks/0/enabled", + "path": "/notification_rules/0/warning_blackhole", "value": false } ] @@ -2205,18 +2312,18 @@ } }, { - "description": "a PATCH request for a single check", - "provider_state": "no entity exists", + "description": "a PATCH request to change properties for a single notification rule", + "provider_state": "no notification rule exists", "request": { "method": "patch", - "path": "/checks/www.example.com:SSH", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/checks/0/enabled", + "path": "/notification_rules/0/warning_blackhole", "value": false } ] @@ -2228,46 +2335,85 @@ }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a GET request for sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a PATCH request to change properties for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { - "method": "get", - "path": "/media/abc_sms" + "method": "patch", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "request": { + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a single notification rule", + "provider_state": "no notification rule exists", + "request": { + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "body": null + }, + "response": { + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ - { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, - "links": { - "contacts": [ - "abc" - ] - } - } + "errors": [ + "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a GET request for all media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a DELETE request for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", + "request": { + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a GET request for all notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { "method": "get", - "path": "/media" + "path": "/notification_rules" }, "response": { "status": 200, @@ -2275,39 +2421,44 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ - { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3, - "links": { - "contacts": [ - "abc" - ] - } - }, + "notification_rules": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, - "links": { - "contacts": [ - "abc" - ] - } + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } } }, { - "description": "a GET request for email and sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a GET request for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { "method": "get", - "path": "/media/abc_email,abc_sms" + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51" }, "response": { "status": 200, @@ -2315,39 +2466,71 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ + "notification_rules": [ { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3, - "links": { - "contacts": [ - "abc" - ] - } + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false }, { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, - "links": { - "contacts": [ - "abc" - ] - } + "id": "20f182fc-6e32-4794-9007-97366d162c51", + "tags": [ + "physical" + ], + "regex_tags": [ + + ], + "entities": [ + "example.com" + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": true, + "critical_blackhole": true } ] } } }, { - "description": "a GET request for sms media", - "provider_state": "no contact exists", + "description": "a GET request for a single notification rule", + "provider_state": "no notification rule exists", "request": { "method": "get", - "path": "/media/abc_sms" + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" }, "response": { "status": 404, @@ -2356,64 +2539,72 @@ }, "body": { "errors": [ - "could not find contact 'abc'" + "could not find notification rules '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a POST request with two media", - "provider_state": "a contact with id 'abc' exists", + "description": "a GET request for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "post", - "path": "/contacts/abc/media", + "method": "get", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ - { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 - }, + "notification_rules": [ { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3 + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } - }, - "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "abc_sms", - "abc_email" - ] } }, { - "description": "a POST request with one medium", + "description": "a POST request with one set of pagerduty credentials", "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/contacts/abc/media", + "path": "/contacts/abc/pagerduty_credentials", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "media": [ + "pagerduty_credentials": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } @@ -2424,26 +2615,26 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "abc_sms" + "abc" ] } }, { - "description": "a POST request with one medium", + "description": "a POST request with one set of pagerduty credentials", "provider_state": "no contact exists", "request": { "method": "post", - "path": "/contacts/abc/media", + "path": "/contacts/abc/pagerduty_credentials", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "media": [ + "pagerduty_credentials": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } @@ -2461,24 +2652,19 @@ } }, { - "description": "a PATCH request for email and sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a PATCH request for pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { "method": "patch", - "path": "/media/abc_email,abc_sms", + "path": "/pagerduty_credentials/abc", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/media/0/interval", - "value": 50 - }, - { - "op": "replace", - "path": "/media/0/rollup_threshold", - "value": 3 + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" } ] }, @@ -2488,49 +2674,77 @@ } }, { - "description": "a PATCH request for email media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a PATCH request for pagerduty credentials", + "provider_state": "no contact exists", "request": { "method": "patch", - "path": "/media/abc_email", + "path": "/pagerduty_credentials/abc", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/media/0/interval", - "value": 50 - }, - { - "op": "replace", - "path": "/media/0/rollup_threshold", - "value": 3 + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" } ] }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contact 'abc'" + ] + } } }, { - "description": "a PATCH request for email media", - "provider_state": "no contact exists", + "description": "a PATCH request for pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", "request": { "method": "patch", - "path": "/media/abc_email", + "path": "/pagerduty_credentials/abc,872", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/media/0/interval", - "value": 50 + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" } ] }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for one set of pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", + "request": { + "method": "delete", + "path": "/pagerduty_credentials/abc", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for one set of pagerduty credentials", + "provider_state": "no contact exists", + "request": { + "method": "delete", + "path": "/pagerduty_credentials/abc", + "body": null + }, "response": { "status": 404, "headers": { @@ -2544,11 +2758,11 @@ } }, { - "description": "a DELETE request for two media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a DELETE request for two sets of pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", "request": { "method": "delete", - "path": "/media/abc_email,abc_sms", + "path": "/pagerduty_credentials/abc,872", "body": null }, "response": { @@ -2557,25 +2771,65 @@ } }, { - "description": "a DELETE request for one medium", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a GET request for all pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { - "method": "delete", - "path": "/media/abc_email", - "body": null + "method": "get", + "path": "/pagerduty_credentials" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "pagerduty_credentials": [ + { + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" + } + ] + } } }, { - "description": "a DELETE request for one medium", + "description": "a GET request for two sets of pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", + "request": { + "method": "get", + "path": "/pagerduty_credentials/abc,872" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "pagerduty_credentials": [ + { + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" + }, + { + "service_key": "mno", + "subdomain": "pqr", + "username": "stu", + "password": "vwx" + } + ] + } + } + }, + { + "description": "a GET request for one set of pagerduty credentials", "provider_state": "no contact exists", "request": { - "method": "delete", - "path": "/media/abc_email", - "body": null + "method": "get", + "path": "/pagerduty_credentials/abc" }, "response": { "status": 404, @@ -2588,6 +2842,30 @@ ] } } + }, + { + "description": "a GET request for one set of pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", + "request": { + "method": "get", + "path": "/pagerduty_credentials/abc" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "pagerduty_credentials": [ + { + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" + } + ] + } + } } ], "metadata": { diff --git a/spec/service_consumers/provider_states_for_flapjack-diner.rb b/spec/service_consumers/provider_states_for_flapjack-diner.rb index 679241b6d..7a1a60c63 100644 --- a/spec/service_consumers/provider_states_for_flapjack-diner.rb +++ b/spec/service_consumers/provider_states_for_flapjack-diner.rb @@ -234,7 +234,7 @@ end end - provider_state "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists" do + provider_state "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists" do set_up do redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') @@ -284,5 +284,70 @@ end end + provider_state "a contact with id 'abc' has pagerduty credentials" do + set_up do + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + contact_data = {'id' => 'abc', + 'first_name' => 'Jim', + 'last_name' => 'Smith', + 'email' => 'jims@example.com', + 'timezone' => 'UTC', + 'tags' => ['admin', 'night_shift']} + contact = Flapjack::Data::Contact.add(contact_data, :redis => redis) + + pdc_data = { + 'service_key' => 'abc', + 'subdomain' => 'def', + 'username' => 'ghi', + 'password' => 'jkl', + } + contact.set_pagerduty_credentials(pdc_data) + end + + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end + + provider_state "contacts with ids 'abc' and '872' have pagerduty credentials" do + set_up do + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + contact_data = {'id' => 'abc', + 'first_name' => 'Jim', + 'last_name' => 'Smith', + 'email' => 'jims@example.com', + 'timezone' => 'UTC', + 'tags' => ['admin', 'night_shift']} + contact = Flapjack::Data::Contact.add(contact_data, :redis => redis) + contact_data_2 = {'id' => '872', + 'first_name' => 'John', + 'last_name' => 'Smith', + 'email' => 'jsmith@example.com'} + contact_2 = Flapjack::Data::Contact.add(contact_data_2, :redis => redis) + + pdc_data = { + 'service_key' => 'abc', + 'subdomain' => 'def', + 'username' => 'ghi', + 'password' => 'jkl', + } + contact.set_pagerduty_credentials(pdc_data) + pdc_data_2 = { + 'service_key' => 'mno', + 'subdomain' => 'pqr', + 'username' => 'stu', + 'password' => 'vwx', + } + contact_2.set_pagerduty_credentials(pdc_data_2) + end + + tear_down do + Flapjack::Gateways::JSONAPI.instance_variable_get('@logger').messages.clear + redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') + redis.flushdb + end + end end \ No newline at end of file From b8e8b87bd4e83abd19beaa26b032ab2fc2b77908 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 26 Sep 2014 14:24:40 +0930 Subject: [PATCH 20/69] pacts for report specs --- .../pacts/flapjack-diner_v1.0.json | 4378 ++++++++++++----- .../provider_states_for_flapjack-diner.rb | 7 +- 2 files changed, 3028 insertions(+), 1357 deletions(-) diff --git a/spec/service_consumers/pacts/flapjack-diner_v1.0.json b/spec/service_consumers/pacts/flapjack-diner_v1.0.json index a45d2a991..764fc315c 100644 --- a/spec/service_consumers/pacts/flapjack-diner_v1.0.json +++ b/spec/service_consumers/pacts/flapjack-diner_v1.0.json @@ -363,19 +363,34 @@ } }, { - "description": "a POST request with one entity", - "provider_state": "no entity exists", + "description": "a POST request with one notification rule", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/entities", + "path": "/contacts/abc/notification_rules", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "notification_rules": [ { - "name": "example.org", - "id": "57_example" + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } @@ -386,28 +401,106 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "57_example" + { + "json_class": "Pact::Term", + "data": { + "generate": "05983623-fcef-42da-af44-ed6990b500fa", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + } ] } }, { - "description": "a POST request with two entities", - "provider_state": "no entity exists", + "description": "a POST request with one notification rule", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/entities", + "path": "/contacts/abc/notification_rules", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "notification_rules": [ { - "name": "example.org", - "id": "57_example" + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + } + ] + } + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contact 'abc'" + ] + } + } + }, + { + "description": "a POST request with two notification rules", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "post", + "path": "/contacts/abc/notification_rules", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "notification_rules": [ + { + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false }, { - "name": "example2.org", - "id": "58" + "entity_tags": null, + "entities": [ + "foo-app-02.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": true, + "critical_blackhole": false } ] } @@ -418,25 +511,37 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "57_example", - "58" + { + "json_class": "Pact::Term", + "data": { + "generate": "05983623-fcef-42da-af44-ed6990b500fa", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + }, + { + "json_class": "Pact::Term", + "data": { + "generate": "20f182fc-6e32-4794-9007-97366d162c51", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + } ] } }, { - "description": "a PATCH request for a single entity", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a PATCH request to change properties for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { "method": "patch", - "path": "/entities/1234", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" + "path": "/notification_rules/0/warning_blackhole", + "value": false } ] }, @@ -446,19 +551,19 @@ } }, { - "description": "a PATCH request for a single entity", - "provider_state": "no entity exists", + "description": "a PATCH request to change properties for a single notification rule", + "provider_state": "no notification rule exists", "request": { "method": "patch", - "path": "/entities/1234", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" + "path": "/notification_rules/0/warning_blackhole", + "value": false } ] }, @@ -469,221 +574,336 @@ }, "body": { "errors": [ - "could not find entity '1234'" + "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a GET request for all entities", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a PATCH request to change properties for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { - "method": "get", - "path": "/entities" - }, - "response": { - "status": 200, + "method": "patch", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, - "body": { - "entities": [ - { - "name": "www.example.com", - "id": "1234" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for all entities", - "provider_state": "no entity exists", + "description": "a DELETE request for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "get", - "path": "/entities" + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "body": null }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "entities": [ - - ] - } + "status": 204, + "body": "" } }, { - "description": "a GET request for a single entity", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a DELETE request for a single notification rule", + "provider_state": "no notification rule exists", "request": { - "method": "get", - "path": "/entities/1234" + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "body": null }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "entities": [ - { - "name": "www.example.com", - "id": "1234" - } + "errors": [ + "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a GET request for a single entity", - "provider_state": "no entity exists", + "description": "a DELETE request for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", + "request": { + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a GET request for all notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { "method": "get", - "path": "/entities/1234" + "path": "/notification_rules" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find entities: '1234'" - ] - } + "notification_rules": [ + { + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + } + ] + } } }, { - "description": "a POST request with one contact", - "provider_state": "no contact exists", + "description": "a GET request for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { - "method": "post", - "path": "/contacts", + "method": "get", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "contacts": [ + "notification_rules": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", + "id": "05983623-fcef-42da-af44-ed6990b500fa", "tags": [ - "admin", - "night_shift" - ] + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + }, + { + "id": "20f182fc-6e32-4794-9007-97366d162c51", + "tags": [ + "physical" + ], + "regex_tags": [ + + ], + "entities": [ + "example.com" + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": true, + "critical_blackhole": true } ] } + } + }, + { + "description": "a GET request for a single notification rule", + "provider_state": "no notification rule exists", + "request": { + "method": "get", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" }, "response": { - "status": 201, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - "abc" - ] + "body": { + "errors": [ + "could not find notification rules '05983623-fcef-42da-af44-ed6990b500fa'" + ] + } } }, { - "description": "a POST request with one contact", + "description": "a GET request for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "request": { + "method": "get", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "notification_rules": [ + { + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + } + ] + } + } + }, + { + "description": "a POST request with one set of pagerduty credentials", "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/contacts", + "path": "/contacts/abc/pagerduty_credentials", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "pagerduty_credentials": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } }, "response": { - "status": 409, + "status": 201, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": { - "errors": [ - "Contacts already exist with the following IDs: abc" - ] - } + "body": [ + "abc" + ] } }, { - "description": "a POST request with two contacts", + "description": "a POST request with one set of pagerduty credentials", "provider_state": "no contact exists", "request": { "method": "post", - "path": "/contacts", + "path": "/contacts/abc/pagerduty_credentials", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ - { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] - }, + "pagerduty_credentials": [ { - "id": "def", - "first_name": "Joan", - "last_name": "Smith", - "email": "joans@example.com" + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } }, "response": { - "status": 201, + "status": 422, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - "abc", - "def" - ] + "body": { + "errors": [ + "Contact id: 'abc' could not be loaded" + ] + } } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a PATCH request for pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { "method": "patch", - "path": "/contacts/abc", + "path": "/pagerduty_credentials/abc", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" } ] }, @@ -693,63 +913,19 @@ } }, { - "description": "a PATCH requestto change a link for a single contact", - "provider_state": "a contact with id '872' exists", + "description": "a PATCH request for pagerduty credentials", + "provider_state": "no contact exists", "request": { "method": "patch", - "path": "/contacts/872", + "path": "/pagerduty_credentials/abc", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" - } - ] - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request to change links for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", - "request": { - "method": "patch", - "path": "/contacts/abc,872", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" - } - ] - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "no contact exists", - "request": { - "method": "patch", - "path": "/contacts/323", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" + "op": "replace", + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" } ] }, @@ -760,25 +936,25 @@ }, "body": { "errors": [ - "could not find contacts '323'" + "could not find contact 'abc'" ] } } }, { - "description": "a PATCH request to change properties for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a PATCH request for pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", "request": { "method": "patch", - "path": "/contacts/abc,872", + "path": "/pagerduty_credentials/abc,872", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" } ] }, @@ -788,11 +964,11 @@ } }, { - "description": "a DELETE request for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a DELETE request for one set of pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { "method": "delete", - "path": "/contacts/abc", + "path": "/pagerduty_credentials/abc", "body": null }, "response": { @@ -801,11 +977,11 @@ } }, { - "description": "a DELETE request for a single contact", + "description": "a DELETE request for one set of pagerduty credentials", "provider_state": "no contact exists", "request": { "method": "delete", - "path": "/contacts/abc", + "path": "/pagerduty_credentials/abc", "body": null }, "response": { @@ -815,17 +991,17 @@ }, "body": { "errors": [ - "could not find contacts 'abc'" + "could not find contact 'abc'" ] } } }, { - "description": "a DELETE request for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a DELETE request for two sets of pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", "request": { "method": "delete", - "path": "/contacts/abc,872", + "path": "/pagerduty_credentials/abc,872", "body": null }, "response": { @@ -834,11 +1010,11 @@ } }, { - "description": "a GET request for all contacts", - "provider_state": "a contact with id 'abc' exists", + "description": "a GET request for all pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { "method": "get", - "path": "/contacts" + "path": "/pagerduty_credentials" }, "response": { "status": 200, @@ -846,28 +1022,23 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "contacts": [ + "pagerduty_credentials": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } } }, { - "description": "a GET request for all contacts", - "provider_state": "no contact exists", + "description": "a GET request for two sets of pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", "request": { "method": "get", - "path": "/contacts" + "path": "/pagerduty_credentials/abc,872" }, "response": { "status": 200, @@ -875,178 +1046,219 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "contacts": [ - + "pagerduty_credentials": [ + { + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" + }, + { + "service_key": "mno", + "subdomain": "pqr", + "username": "stu", + "password": "vwx" + } ] } } }, { - "description": "a GET request for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a GET request for one set of pagerduty credentials", + "provider_state": "no contact exists", "request": { "method": "get", - "path": "/contacts/abc" + "path": "/pagerduty_credentials/abc" }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "contacts": [ - { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] - } + "errors": [ + "could not find contact 'abc'" ] } } }, { - "description": "a GET request for a single contact", - "provider_state": "no contact exists", + "description": "a GET request for one set of pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { "method": "get", - "path": "/contacts/abc" + "path": "/pagerduty_credentials/abc" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find contacts 'abc'" + "pagerduty_credentials": [ + { + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" + } ] } } }, { - "description": "a POST request with one check", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for a scheduled_maintenance report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/checks", + "method": "get", + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ + "scheduled_maintenance_reports": [ { - "name": "PING", - "entity_id": "1234" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } + } + }, + { + "description": "a GET request for a downtime report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/downtime_report/entities" }, "response": { - "status": 201, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - "www.example.com:PING" - ] + "body": { + "downtime_reports": [ + { + } + ] + } } }, { - "description": "a POST request with two checks", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for a scheduled_maintenance report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/checks", + "method": "get", + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ + "scheduled_maintenance_reports": [ { - "name": "SSH", - "entity_id": "1234" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } }, { - "name": "PING", - "entity_id": "1234" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } + } + }, + { + "description": "a GET request for a downtime report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/downtime_report/checks/www.example.com:SSH" }, "response": { - "status": 201, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - "www.example.com:SSH", - "www.example.com:PING" - ] + "body": { + "downtime_reports": [ + { + } + ] + } } }, { - "description": "a PATCH request for a single check", + "description": "a GET request for a outage report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/checks/0/enabled", - "value": false - } - ] + "method": "get", + "path": "/outage_report/checks/www.example.com:SSH" }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for a single check", - "provider_state": "no entity exists", - "request": { - "method": "patch", - "path": "/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/checks/0/enabled", - "value": false - } - ] - }, - "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find entity 'www.example.com'" + "outage_reports": [ + { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } ] } } }, { - "description": "a GET request for all checks", - "provider_state": "no entity exists", + "description": "a time limited GET request for a scheduled_maintenance report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/checks" + "path": "/scheduled_maintenance_report/entities", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" }, "response": { "status": 200, @@ -1054,18 +1266,31 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } ] } } }, { - "description": "a GET request for all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a time limited GET request for a scheduled_maintenance report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/checks" + "path": "/scheduled_maintenance_report/entities/1234,5678", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" }, "response": { "status": 200, @@ -1073,14 +1298,30 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ + "scheduled_maintenance_reports": [ { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", + "scheduled_maintenances": [ + + ], "links": { - "entities": [ + "entity": [ "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" ] } } @@ -1089,11 +1330,12 @@ } }, { - "description": "a GET request for check 'www.example.com:SSH'", + "description": "a time limited GET request for a unscheduled_maintenance report on all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/checks/www.example.com:SSH" + "path": "/unscheduled_maintenance_report/checks", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" }, "response": { "status": 200, @@ -1101,14 +1343,17 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ + "unscheduled_maintenance_reports": [ { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", + "unscheduled_maintenances": [ + + ], "links": { - "entities": [ + "entity": [ "1234" + ], + "check": [ + "www.example.com:SSH" ] } } @@ -1117,958 +1362,2582 @@ } }, { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "no entity exists", + "description": "a time limited GET request for a outage report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/checks/www.example.com:SSH" + "path": "/outage_report/entities/1234", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find entity checks: 'www.example.com:SSH'" + "outage_reports": [ + { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } ] } } }, { - "description": "a POST request with one test notification", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for a outage report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/test_notifications/entities/1234", + "method": "get", + "path": "/outage_report/checks" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ + "outage_reports": [ { - "summary": "testing" + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two test notifications", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for a outage report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/test_notifications/entities/1234", + "method": "get", + "path": "/outage_report/entities/1234,5678" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ + "outage_reports": [ { - "summary": "testing" + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } }, { - "summary": "more tests" + "outages": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two test notifications", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for a scheduled_maintenance report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/test_notifications/entities/1234,5678", + "method": "get", + "path": "/scheduled_maintenance_report/entities" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ - { - "summary": "testing" - }, + "scheduled_maintenance_reports": [ { - "summary": "more tests" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one test notification", - "provider_state": "no entity exists", + "description": "a time-limited GET request for a unscheduled_maintenance report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/test_notifications/entities/1234", + "method": "get", + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ + "unscheduled_maintenance_reports": [ { - "summary": "testing" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } + } + }, + { + "description": "a time limited GET request for a downtime report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/downtime_report/checks", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" }, "response": { - "status": 404, + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { - "errors": [ - "could not find entity '1234'" + "downtime_reports": [ + { + } ] } } }, { - "description": "a POST request with one test notification", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for a status report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/test_notifications/entities/1234,5678", + "method": "get", + "path": "/status_report/checks/www.example.com:SSH,www2.example.com:PING" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ + "status_reports": [ + { + }, { - "summary": "testing" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one test notification", + "description": "a time limited GET request for a outage report on all entities", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", + "method": "get", + "path": "/outage_report/entities", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ + "outage_reports": [ { - "summary": "testing" + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two test notifications", + "description": "a time limited GET request for a unscheduled_maintenance report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", + "method": "get", + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ - { - "summary": "testing" - }, + "unscheduled_maintenance_reports": [ { - "summary": "more tests" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two test notifications", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a GET request for a outage report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH,www.example.com:PING", + "method": "get", + "path": "/outage_report/entities/1234" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ - { - "summary": "testing" - }, + "outage_reports": [ { - "summary": "more tests" + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one test notification", - "provider_state": "no check exists", + "description": "a time limited GET request for a scheduled_maintenance report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", + "method": "get", + "path": "/scheduled_maintenance_report/checks", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ + "scheduled_maintenance_reports": [ { - "summary": "testing" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } + } + }, + { + "description": "a time limited GET request for a unscheduled_maintenance report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/unscheduled_maintenance_report/entities/1234", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" }, "response": { - "status": 404, + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { - "errors": [ - "could not find entity 'www.example.com'" + "unscheduled_maintenance_reports": [ + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } ] } } }, { - "description": "a POST request with one test notification", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a GET request for a status report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH,www.example.com:PING", + "method": "get", + "path": "/status_report/entities/1234,5678" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ + "status_reports": [ + { + }, { - "summary": "testing" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for a unscheduled_maintenance report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "method": "get", + "path": "/unscheduled_maintenance_report/checks" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "unscheduled_maintenance_reports": [ { - "start_time": "2014-09-26T09:53:06+09:30", - "duration": 3600, - "summary": "working" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a time-limited GET request for a outage report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "method": "get", + "path": "/outage_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "outage_reports": [ { - "start_time": "2014-09-26T09:53:07+09:30", - "duration": 3600, - "summary": "working" + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } }, { - "start_time": "2014-09-26T11:53:07+09:30", - "duration": 3600, - "summary": "more work" + "outages": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a time limited GET request for a scheduled_maintenance report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "method": "get", + "path": "/scheduled_maintenance_report/entities/1234", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-26T09:53:07+09:30", - "duration": 3600, - "summary": "working" - }, + "scheduled_maintenance_reports": [ { - "start_time": "2014-09-26T11:53:07+09:30", - "duration": 3600, - "summary": "more work" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "no entity exists", + "description": "a GET request for a status report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "method": "get", + "path": "/status_report/checks/www.example.com:SSH" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "status_reports": [ { - "start_time": "2014-09-26T09:53:07+09:30", - "duration": 3600, - "summary": "working" } ] } + } + }, + { + "description": "a GET request for a scheduled_maintenance report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "get", + "path": "/scheduled_maintenance_report/entities/1234,5678" }, "response": { - "status": 404, + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { - "errors": [ - "could not find entity '1234'" + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } + } ] } } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a time limited GET request for a downtime report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "method": "get", + "path": "/downtime_report/checks/www.example.com:SSH", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "downtime_reports": [ { - "start_time": "2014-09-26T09:53:07+09:30", - "duration": 3600, - "summary": "working" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for a unscheduled_maintenance report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "method": "get", + "path": "/unscheduled_maintenance_report/entities" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "unscheduled_maintenance_reports": [ { - "duration": 3600, - "summary": "working" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for a status report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "method": "get", + "path": "/status_report/entities/1234" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, + "status_reports": [ { - "duration": 3600, - "summary": "more work" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for a unscheduled_maintenance report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "method": "get", + "path": "/unscheduled_maintenance_report/entities/1234" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, + "unscheduled_maintenance_reports": [ { - "duration": 3600, - "summary": "more work" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "no entity exists", + "description": "a GET request for a downtime report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "method": "get", + "path": "/downtime_report/checks/www.example.com:SSH,www2.example.com:PING" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "downtime_reports": [ + { + }, { - "duration": 3600, - "summary": "working" } ] } - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for a downtime report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "method": "get", + "path": "/downtime_report/entities/1234" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "downtime_reports": [ { - "duration": 3600, - "summary": "working" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-26T09%3A53%3A07%2B09%3A30" - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no entity exists", + "description": "a time limited GET request for a downtime report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-26T09%3A53%3A07%2B09%3A30" + "method": "get", + "path": "/downtime_report/entities/1234", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" }, "response": { - "status": 404, + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { - "errors": [ - "could not find entity '1234'" + "downtime_reports": [ + { + } ] } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a time limited GET request for a downtime report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234,5678", - "query": "start_time=2014-09-26T09%3A53%3A07%2B09%3A30" + "method": "get", + "path": "/downtime_report/entities/1234,5678", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", - "request": { - "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", + "status": 200, "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T09:53:07+09:30" - } - ] - }, - "response": { - "status": 204, - "body": "" + "body": { + "downtime_reports": [ + { + }, + { + } + ] + } } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no entity exists", + "description": "a time limited GET request for a unscheduled_maintenance report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T09:53:07+09:30" - } - ] + "method": "get", + "path": "/unscheduled_maintenance_report/entities/1234,5678", + "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" }, "response": { - "status": 404, + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { - "errors": [ - "could not find entity '1234'" + "unscheduled_maintenance_reports": [ + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } + } ] } } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for a scheduled_maintenance report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/entities/1234,5678", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T09:53:07+09:30" - } - ] + "method": "get", + "path": "/scheduled_maintenance_report/entities/1234" }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "scheduled_maintenance_reports": [ { - "start_time": "2014-09-26T09:53:07+09:30", - "duration": 3600, - "summary": "working" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a unscheduled_maintenance report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/unscheduled_maintenance_report/entities/1234,5678" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "unscheduled_maintenance_reports": [ { - "start_time": "2014-09-26T09:53:07+09:30", - "duration": 3600, - "summary": "working" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } }, { - "start_time": "2014-09-26T11:53:07+09:30", - "duration": 3600, - "summary": "more work" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a GET request for a outage report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "method": "get", + "path": "/outage_report/entities" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-26T09:53:07+09:30", - "duration": 3600, - "summary": "working" - }, + "outage_reports": [ { - "start_time": "2014-09-26T11:53:07+09:30", - "duration": 3600, - "summary": "more work" + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "no check exists", + "description": "a time-limited GET request for a scheduled_maintenance report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "scheduled_maintenance_reports": [ { - "start_time": "2014-09-26T09:53:07+09:30", - "duration": 3600, - "summary": "working" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity 'www.example.com'" - ] - } } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a time limited GET request for a downtime report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "method": "get", + "path": "/downtime_report/entities", + "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "downtime_reports": [ { - "start_time": "2014-09-26T09:53:07+09:30", - "duration": 3600, - "summary": "working" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", + "description": "a time limited GET request for a scheduled_maintenance report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH", + "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "scheduled_maintenance_reports": [ { - "duration": 3600, - "summary": "working" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a time-limited GET request for a downtime report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/downtime_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "downtime_reports": [ { - "duration": 3600, - "summary": "working" }, { - "duration": 3600, - "summary": "more work" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a GET request for a downtime report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "method": "get", + "path": "/downtime_report/entities/1234,5678" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "downtime_reports": [ { - "duration": 3600, - "summary": "working" }, { - "duration": 3600, - "summary": "more work" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "no check exists", + "description": "a time limited GET request for a outage report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/outage_report/checks/www.example.com:SSH", + "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "outage_reports": [ { - "duration": 3600, - "summary": "working" + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity 'www.example.com'" - ] - } } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a time limited GET request for a outage report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "method": "get", + "path": "/outage_report/checks", + "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "outage_reports": [ { - "duration": 3600, - "summary": "working" + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a DELETE request for a scheduled maintenance period", + "description": "a GET request for a scheduled_maintenance report on all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-26T09%3A53%3A07%2B09%3A30" + "method": "get", + "path": "/scheduled_maintenance_report/checks" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } + ] + } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no check exists", + "description": "a GET request for a unscheduled_maintenance report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-26T09%3A53%3A07%2B09%3A30" + "method": "get", + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING" }, "response": { - "status": 404, + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { - "errors": [ - "could not find entity 'www.example.com'" + "unscheduled_maintenance_reports": [ + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } + } ] } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a time limited GET request for a outage report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", - "query": "start_time=2014-09-26T09%3A53%3A07%2B09%3A30" + "method": "get", + "path": "/outage_report/entities/1234,5678", + "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "outage_reports": [ + { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "outages": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } + } + ] + } } }, { - "description": "a PATCH request for an unscheduled maintenance period", + "description": "a GET request for a unscheduled_maintenance report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", - "headers": { + "method": "get", + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "unscheduled_maintenance_reports": [ + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } + ] + } + } + }, + { + "description": "a time limited GET request for a unscheduled_maintenance report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/unscheduled_maintenance_report/entities", + "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "unscheduled_maintenance_reports": [ + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } + ] + } + } + }, + { + "description": "a GET request for a status report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/status_report/entities" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "status_reports": [ + { + } + ] + } + } + }, + { + "description": "a GET request for a status report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/status_report/checks" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "status_reports": [ + { + } + ] + } + } + }, + { + "description": "a GET request for a outage report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "get", + "path": "/outage_report/checks/www.example.com:SSH,www2.example.com:PING" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "outage_reports": [ + { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "outages": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } + } + ] + } + } + }, + { + "description": "a GET request for a downtime report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/downtime_report/checks" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "downtime_reports": [ + { + } + ] + } + } + }, + { + "description": "a POST request with one test notification", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/test_notifications/entities/1234,5678", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one test notification", + "provider_state": "no entity exists", + "request": { + "method": "post", + "path": "/test_notifications/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + } + ] + } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } + } + }, + { + "description": "a POST request with two test notifications", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/test_notifications/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + }, + { + "summary": "more tests" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one test notification", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/test_notifications/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two test notifications", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/test_notifications/entities/1234,5678", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + }, + { + "summary": "more tests" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one test notification", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH,www2.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one test notification", + "provider_state": "no check exists", + "request": { + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + } + ] + } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } + } + }, + { + "description": "a POST request with two test notifications", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + }, + { + "summary": "more tests" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one test notification", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two test notifications", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH,www2.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + }, + { + "summary": "more tests" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one entity", + "provider_state": "no entity exists", + "request": { + "method": "post", + "path": "/entities", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "entities": [ + { + "name": "example.org", + "id": "57_example" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example" + ] + } + }, + { + "description": "a POST request with two entities", + "provider_state": "no entity exists", + "request": { + "method": "post", + "path": "/entities", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "entities": [ + { + "name": "example.org", + "id": "57_example" + }, + { + "name": "example2.org", + "id": "58" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example", + "58" + ] + } + }, + { + "description": "a PATCH request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "patch", + "path": "/entities/1234", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/entities/0/name", + "value": "example3.com" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for a single entity", + "provider_state": "no entity exists", + "request": { + "method": "patch", + "path": "/entities/1234", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/entities/0/name", + "value": "example3.com" + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } + } + }, + { + "description": "a GET request for all entities", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "get", + "path": "/entities" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "entities": [ + { + "name": "www.example.com", + "id": "1234" + } + ] + } + } + }, + { + "description": "a GET request for all entities", + "provider_state": "no entity exists", + "request": { + "method": "get", + "path": "/entities" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "entities": [ + + ] + } + } + }, + { + "description": "a GET request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "get", + "path": "/entities/1234" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "entities": [ + { + "name": "www.example.com", + "id": "1234" + } + ] + } + } + }, + { + "description": "a GET request for a single entity", + "provider_state": "no entity exists", + "request": { + "method": "get", + "path": "/entities/1234" + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entities: '1234'" + ] + } + } + }, + { + "description": "a POST request with one check", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/checks", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "checks": [ + { + "name": "SSH", + "entity_id": "1234" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:SSH" + ] + } + }, + { + "description": "a POST request with two checks", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/checks", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "checks": [ + { + "name": "SSH", + "entity_id": "1234" + }, + { + "name": "PING", + "entity_id": "5678" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:SSH", + "www2.example.com:PING" + ] + } + }, + { + "description": "a PATCH request for a single check", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "patch", + "path": "/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/checks/0/enabled", + "value": false + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for a single check", + "provider_state": "no entity exists", + "request": { + "method": "patch", + "path": "/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/checks/0/enabled", + "value": false + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } + } + }, + { + "description": "a GET request for all checks", + "provider_state": "no entity exists", + "request": { + "method": "get", + "path": "/checks" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "checks": [ + + ] + } + } + }, + { + "description": "a GET request for all checks", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/checks" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "checks": [ + { + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } + } + ] + } + } + }, + { + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/checks/www.example.com:SSH" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "checks": [ + { + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } + } + ] + } + } + }, + { + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "no entity exists", + "request": { + "method": "get", + "path": "/checks/www.example.com:SSH" + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity checks: 'www.example.com:SSH'" + ] + } + } + }, + { + "description": "a POST request with one contact", + "provider_state": "no contact exists", + "request": { + "method": "post", + "path": "/contacts", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc" + ] + } + }, + { + "description": "a POST request with one contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "post", + "path": "/contacts", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + } + ] + } + }, + "response": { + "status": 409, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "Contacts already exist with the following IDs: abc" + ] + } + } + }, + { + "description": "a POST request with two contacts", + "provider_state": "no contact exists", + "request": { + "method": "post", + "path": "/contacts", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + }, + { + "id": "def", + "first_name": "Joan", + "last_name": "Smith", + "email": "joans@example.com" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc", + "def" + ] + } + }, + { + "description": "a PATCH request to change properties for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", + "request": { + "method": "patch", + "path": "/contacts/abc,872", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request to change properties for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "patch", + "path": "/contacts/323", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts '323'" + ] + } + } + }, + { + "description": "a PATCH requestto change a link for a single contact", + "provider_state": "a contact with id '872' exists", + "request": { + "method": "patch", + "path": "/contacts/872", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request to change properties for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "patch", + "path": "/contacts/abc", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request to change links for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", + "request": { + "method": "patch", + "path": "/contacts/abc,872", + "headers": { "Content-Type": "application/json-patch+json" }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T09:53:07+09:30" - } - ] + "body": [ + { + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts 'abc'" + ] + } + } + }, + { + "description": "a DELETE request for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", + "request": { + "method": "delete", + "path": "/contacts/abc,872", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a GET request for all contacts", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "get", + "path": "/contacts" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + } + ] + } + } + }, + { + "description": "a GET request for all contacts", + "provider_state": "no contact exists", + "request": { + "method": "get", + "path": "/contacts" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "contacts": [ + + ] + } + } + }, + { + "description": "a GET request for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "get", + "path": "/contacts/abc" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + } + ] + } + } + }, + { + "description": "a GET request for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "get", + "path": "/contacts/abc" + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts 'abc'" + ] + } + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-26T14:24:24+09:30", + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "no entity exists", + "request": { + "method": "post", + "path": "/scheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-26T14:24:24+09:30", + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } + } + }, + { + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/scheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-26T14:24:24+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-26T16:24:24+09:30", + "duration": 3600, + "summary": "more work" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/scheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-26T14:24:24+09:30", + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-09-26T14:24:24+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-26T16:24:24+09:30", + "duration": 3600, + "summary": "more work" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/entities/1234,5678", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 204, @@ -2076,47 +3945,53 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no check exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "no entity exists", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T09:53:07+09:30" - } - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 404, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find entity '1234'" ] } } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www.example.com:PING' exist", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www.example.com:PING", + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T09:53:07+09:30" - } - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } }, "response": { "status": 204, @@ -2124,185 +3999,112 @@ } }, { - "description": "a POST request with one notification rule", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/contacts/abc/notification_rules", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "notification_rules": [ + "unscheduled_maintenances": [ { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - { - "json_class": "Pact::Term", - "data": { - "generate": "05983623-fcef-42da-af44-ed6990b500fa", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - } - ] + "status": 204, + "body": "" } }, { - "description": "a POST request with one notification rule", - "provider_state": "no contact exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/contacts/abc/notification_rules", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "notification_rules": [ + "unscheduled_maintenances": [ { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" } ] } }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-26T14%3A24%3A24%2B09%3A30" + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no entity exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-26T14%3A24%3A24%2B09%3A30" + }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find contact 'abc'" + "could not find entity '1234'" ] } } }, { - "description": "a POST request with two notification rules", - "provider_state": "a contact with id 'abc' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "post", - "path": "/contacts/abc/notification_rules", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "notification_rules": [ - { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - }, - { - "entity_tags": null, - "entities": [ - "foo-app-02.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": true, - "critical_blackhole": false - } - ] - } + "method": "delete", + "path": "/scheduled_maintenances/entities/1234,5678", + "query": "start_time=2014-09-26T14%3A24%3A24%2B09%3A30" }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - { - "json_class": "Pact::Term", - "data": { - "generate": "05983623-fcef-42da-af44-ed6990b500fa", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - }, - { - "json_class": "Pact::Term", - "data": { - "generate": "20f182fc-6e32-4794-9007-97366d162c51", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - } - ] + "status": 204, + "body": "" } }, { - "description": "a PATCH request to change properties for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T14:24:24+09:30" } ] }, @@ -2312,48 +4114,45 @@ } }, { - "description": "a PATCH request to change properties for a single notification rule", - "provider_state": "no notification rule exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no entity exists", "request": { "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T14:24:24+09:30" } ] }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" + "could not find entity '1234'" ] } } }, - { - "description": "a PATCH request to change properties for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T14:24:24+09:30" } ] }, @@ -2363,45 +4162,23 @@ } }, { - "description": "a DELETE request for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", - "request": { - "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a single notification rule", - "provider_state": "no notification rule exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "body": null - }, - "response": { - "status": 404, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" + "scheduled_maintenances": [ + { + "start_time": "2014-09-26T14:24:24+09:30", + "duration": 3600, + "summary": "working" + } ] } - } - }, - { - "description": "a DELETE request for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", - "request": { - "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", - "body": null }, "response": { "status": 204, @@ -2409,264 +4186,186 @@ } }, { - "description": "a GET request for all notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "no check exists", "request": { - "method": "get", - "path": "/notification_rules" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "notification_rules": [ + "scheduled_maintenances": [ { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "start_time": "2014-09-26T14:24:24+09:30", + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { - "description": "a GET request for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "notification_rules": [ + "scheduled_maintenances": [ { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "start_time": "2014-09-26T14:24:24+09:30", + "duration": 3600, + "summary": "working" }, { - "id": "20f182fc-6e32-4794-9007-97366d162c51", - "tags": [ - "physical" - ], - "regex_tags": [ - - ], - "entities": [ - "example.com" - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": true, - "critical_blackhole": true + "start_time": "2014-09-26T16:24:24+09:30", + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a single notification rule", - "provider_state": "no notification rule exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" - }, - "response": { - "status": 404, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find notification rules '05983623-fcef-42da-af44-ed6990b500fa'" + "scheduled_maintenances": [ + { + "start_time": "2014-09-26T14:24:24+09:30", + "duration": 3600, + "summary": "working" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "notification_rules": [ + "scheduled_maintenances": [ { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "start_time": "2014-09-26T14:24:24+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-26T16:24:24+09:30", + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a POST request with one set of pagerduty credentials", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "post", - "path": "/contacts/abc/pagerduty_credentials", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "pagerduty_credentials": [ + "unscheduled_maintenances": [ { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "abc" - ] + "status": 204, + "body": "" } }, { - "description": "a POST request with one set of pagerduty credentials", - "provider_state": "no contact exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "no check exists", "request": { "method": "post", - "path": "/contacts/abc/pagerduty_credentials", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "pagerduty_credentials": [ + "unscheduled_maintenances": [ { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 422, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, + "status": 404, "body": { "errors": [ - "Contact id: 'abc' could not be loaded" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a PATCH request for pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/pagerduty_credentials/abc", + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/pagerduty_credentials/0/password", - "value": "pswrd" - } - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } }, "response": { "status": 204, @@ -2674,50 +4373,49 @@ } }, { - "description": "a PATCH request for pagerduty credentials", - "provider_state": "no contact exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/pagerduty_credentials/abc", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/pagerduty_credentials/0/password", - "value": "pswrd" - } - ] - }, - "response": { - "status": 404, + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find contact 'abc'" + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a PATCH request for pagerduty credentials", - "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "patch", - "path": "/pagerduty_credentials/abc,872", + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/pagerduty_credentials/0/password", - "value": "pswrd" - } - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } }, "response": { "status": 204, @@ -2725,12 +4423,12 @@ } }, { - "description": "a DELETE request for one set of pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "delete", - "path": "/pagerduty_credentials/abc", - "body": null + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-26T14%3A24%3A25%2B09%3A30" }, "response": { "status": 204, @@ -2738,32 +4436,29 @@ } }, { - "description": "a DELETE request for one set of pagerduty credentials", - "provider_state": "no contact exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no check exists", "request": { "method": "delete", - "path": "/pagerduty_credentials/abc", - "body": null + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-26T14%3A24%3A25%2B09%3A30" }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find contact 'abc'" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a DELETE request for two sets of pagerduty credentials", - "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "delete", - "path": "/pagerduty_credentials/abc,872", - "body": null + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-09-26T14%3A24%3A25%2B09%3A30" }, "response": { "status": 204, @@ -2771,100 +4466,73 @@ } }, { - "description": "a GET request for all pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/pagerduty_credentials" - }, - "response": { - "status": 200, + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, - "body": { - "pagerduty_credentials": [ - { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" - } - ] - } - } - }, - { - "description": "a GET request for two sets of pagerduty credentials", - "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", - "request": { - "method": "get", - "path": "/pagerduty_credentials/abc,872" + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T14:24:25+09:30" + } + ] }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "pagerduty_credentials": [ - { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" - }, - { - "service_key": "mno", - "subdomain": "pqr", - "username": "stu", - "password": "vwx" - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a GET request for one set of pagerduty credentials", - "provider_state": "no contact exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no check exists", "request": { - "method": "get", - "path": "/pagerduty_credentials/abc" + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T14:24:25+09:30" + } + ] }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find contact 'abc'" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a GET request for one set of pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "get", - "path": "/pagerduty_credentials/abc" - }, - "response": { - "status": 200, + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, - "body": { - "pagerduty_credentials": [ - { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T14:24:25+09:30" + } + ] + }, + "response": { + "status": 204, + "body": "" } } ], diff --git a/spec/service_consumers/provider_states_for_flapjack-diner.rb b/spec/service_consumers/provider_states_for_flapjack-diner.rb index 7a1a60c63..e4fc6e942 100644 --- a/spec/service_consumers/provider_states_for_flapjack-diner.rb +++ b/spec/service_consumers/provider_states_for_flapjack-diner.rb @@ -81,15 +81,18 @@ end end - provider_state "checks 'www.example.com:SSH' and 'www.example.com:PING' exist" do + provider_state "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist" do set_up do redis = Flapjack::Gateways::JSONAPI.instance_variable_get('@redis') entity_data = {'id' => '1234', 'name' => 'www.example.com'} Flapjack::Data::Entity.add(entity_data, :redis => redis) + entity_data_2 = {'id' => '5678', 'name' => 'www2.example.com'} + Flapjack::Data::Entity.add(entity_data_2, :redis => redis) + check_data = {'entity_id' => '1234', 'name' => 'SSH'} Flapjack::Data::EntityCheck.add(check_data, :redis => redis) - check_data_2 = {'entity_id' => '1234', 'name' => 'PING'} + check_data_2 = {'entity_id' => '5678', 'name' => 'PING'} Flapjack::Data::EntityCheck.add(check_data_2, :redis => redis) end From 1ca3a3c84cd520f16e949abba1aec2ca5ca9370b Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 26 Sep 2014 14:47:41 +0930 Subject: [PATCH 21/69] final pact data update before PR --- .../pacts/flapjack-diner_v1.0.json | 4280 ++++++++--------- 1 file changed, 2140 insertions(+), 2140 deletions(-) diff --git a/spec/service_consumers/pacts/flapjack-diner_v1.0.json b/spec/service_consumers/pacts/flapjack-diner_v1.0.json index 764fc315c..77ca3414c 100644 --- a/spec/service_consumers/pacts/flapjack-diner_v1.0.json +++ b/spec/service_consumers/pacts/flapjack-diner_v1.0.json @@ -7,51 +7,67 @@ }, "interactions": [ { - "description": "a POST request with one medium", - "provider_state": "a contact with id 'abc' exists", + "description": "a DELETE request for one set of pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { - "method": "post", - "path": "/contacts/abc/media", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "media": [ - { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 - } - ] - } + "method": "delete", + "path": "/pagerduty_credentials/abc", + "body": null }, "response": { - "status": 201, + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for two sets of pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", + "request": { + "method": "delete", + "path": "/pagerduty_credentials/abc,872", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for one set of pagerduty credentials", + "provider_state": "no contact exists", + "request": { + "method": "delete", + "path": "/pagerduty_credentials/abc", + "body": null + }, + "response": { + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - "abc_sms" - ] + "body": { + "errors": [ + "could not find contact 'abc'" + ] + } } }, { - "description": "a POST request with one medium", + "description": "a POST request with one set of pagerduty credentials", "provider_state": "no contact exists", "request": { "method": "post", - "path": "/contacts/abc/media", + "path": "/contacts/abc/pagerduty_credentials", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "media": [ + "pagerduty_credentials": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } @@ -69,27 +85,21 @@ } }, { - "description": "a POST request with two media", + "description": "a POST request with one set of pagerduty credentials", "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/contacts/abc/media", + "path": "/contacts/abc/pagerduty_credentials", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "media": [ - { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 - }, + "pagerduty_credentials": [ { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3 + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } @@ -100,86 +110,121 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "abc_sms", - "abc_email" + "abc" ] } }, { - "description": "a PATCH request for email media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a GET request for one set of pagerduty credentials", + "provider_state": "no contact exists", "request": { - "method": "patch", - "path": "/media/abc_email", + "method": "get", + "path": "/pagerduty_credentials/abc" + }, + "response": { + "status": 404, "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - { - "op": "replace", - "path": "/media/0/interval", - "value": 50 - }, - { - "op": "replace", - "path": "/media/0/rollup_threshold", - "value": 3 - } - ] + "body": { + "errors": [ + "could not find contact 'abc'" + ] + } + } + }, + { + "description": "a GET request for all pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", + "request": { + "method": "get", + "path": "/pagerduty_credentials" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "pagerduty_credentials": [ + { + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" + } + ] + } } }, { - "description": "a PATCH request for email media", - "provider_state": "no contact exists", + "description": "a GET request for one set of pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { - "method": "patch", - "path": "/media/abc_email", + "method": "get", + "path": "/pagerduty_credentials/abc" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - { - "op": "replace", - "path": "/media/0/interval", - "value": 50 - } - ] + "body": { + "pagerduty_credentials": [ + { + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" + } + ] + } + } + }, + { + "description": "a GET request for two sets of pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", + "request": { + "method": "get", + "path": "/pagerduty_credentials/abc,872" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find contact 'abc'" + "pagerduty_credentials": [ + { + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" + }, + { + "service_key": "mno", + "subdomain": "pqr", + "username": "stu", + "password": "vwx" + } ] } } }, { - "description": "a PATCH request for email and sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a PATCH request for pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { "method": "patch", - "path": "/media/abc_email,abc_sms", + "path": "/pagerduty_credentials/abc", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/media/0/interval", - "value": 50 - }, - { - "op": "replace", - "path": "/media/0/rollup_threshold", - "value": 3 + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" } ] }, @@ -189,12 +234,21 @@ } }, { - "description": "a DELETE request for one medium", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a PATCH request for pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", "request": { - "method": "delete", - "path": "/media/abc_email", - "body": null + "method": "patch", + "path": "/pagerduty_credentials/abc,872", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" + } + ] }, "response": { "status": 204, @@ -202,12 +256,21 @@ } }, { - "description": "a DELETE request for one medium", + "description": "a PATCH request for pagerduty credentials", "provider_state": "no contact exists", "request": { - "method": "delete", - "path": "/media/abc_email", - "body": null + "method": "patch", + "path": "/pagerduty_credentials/abc", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" + } + ] }, "response": { "status": 404, @@ -222,104 +285,72 @@ } }, { - "description": "a DELETE request for two media", - "provider_state": "a contact with id 'abc' has email and sms media", - "request": { - "method": "delete", - "path": "/media/abc_email,abc_sms", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a GET request for all media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a POST request with two checks", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/media" - }, - "response": { - "status": 200, + "method": "post", + "path": "/checks", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "media": [ + "checks": [ { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3, - "links": { - "contacts": [ - "abc" - ] - } + "name": "SSH", + "entity_id": "1234" }, { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, - "links": { - "contacts": [ - "abc" - ] - } + "name": "PING", + "entity_id": "5678" } ] } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:SSH", + "www2.example.com:PING" + ] } }, { - "description": "a GET request for email and sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a POST request with one check", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/media/abc_email,abc_sms" - }, - "response": { - "status": 200, + "method": "post", + "path": "/checks", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "media": [ - { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3, - "links": { - "contacts": [ - "abc" - ] - } - }, + "checks": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, - "links": { - "contacts": [ - "abc" - ] - } + "name": "SSH", + "entity_id": "1234" } ] } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "www.example.com:SSH" + ] } }, { - "description": "a GET request for sms media", - "provider_state": "no contact exists", + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "no entity exists", "request": { "method": "get", - "path": "/media/abc_sms" + "path": "/checks/www.example.com:SSH" }, "response": { "status": 404, @@ -328,17 +359,17 @@ }, "body": { "errors": [ - "could not find contact 'abc'" + "could not find entity checks: 'www.example.com:SSH'" ] } } }, { - "description": "a GET request for sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/media/abc_sms" + "path": "/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -346,15 +377,14 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ + "checks": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", "links": { - "contacts": [ - "abc" + "entities": [ + "1234" ] } } @@ -363,86 +393,68 @@ } }, { - "description": "a POST request with one notification rule", - "provider_state": "a contact with id 'abc' exists", + "description": "a GET request for all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/contacts/abc/notification_rules", + "method": "get", + "path": "/checks" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "notification_rules": [ + "checks": [ { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", + "links": { + "entities": [ + "1234" + ] + } } ] } + } + }, + { + "description": "a GET request for all checks", + "provider_state": "no entity exists", + "request": { + "method": "get", + "path": "/checks" }, "response": { - "status": 201, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - { - "json_class": "Pact::Term", - "data": { - "generate": "05983623-fcef-42da-af44-ed6990b500fa", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - } - ] + "body": { + "checks": [ + + ] + } } }, { - "description": "a POST request with one notification rule", - "provider_state": "no contact exists", + "description": "a PATCH request for a single check", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/contacts/abc/notification_rules", + "method": "patch", + "path": "/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "notification_rules": [ - { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - } - ] - } + "body": [ + { + "op": "replace", + "path": "/checks/0/enabled", + "value": false + } + ] }, "response": { "status": 404, @@ -451,710 +463,31 @@ }, "body": { "errors": [ - "could not find contact 'abc'" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a POST request with two notification rules", - "provider_state": "a contact with id 'abc' exists", + "description": "a PATCH request for a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/contacts/abc/notification_rules", + "method": "patch", + "path": "/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "notification_rules": [ - { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - }, - { - "entity_tags": null, - "entities": [ - "foo-app-02.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": true, - "critical_blackhole": false - } - ] - } - }, - "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - { - "json_class": "Pact::Term", - "data": { - "generate": "05983623-fcef-42da-af44-ed6990b500fa", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - }, - { - "json_class": "Pact::Term", - "data": { - "generate": "20f182fc-6e32-4794-9007-97366d162c51", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - } - ] - } - }, - { - "description": "a PATCH request to change properties for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", - "request": { - "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false - } - ] - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request to change properties for a single notification rule", - "provider_state": "no notification rule exists", - "request": { - "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false - } - ] - }, - "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" - ] - } - } - }, - { - "description": "a PATCH request to change properties for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", - "request": { - "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false - } - ] - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", - "request": { - "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a single notification rule", - "provider_state": "no notification rule exists", - "request": { - "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "body": null - }, - "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" - ] - } - } - }, - { - "description": "a DELETE request for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", - "request": { - "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a GET request for all notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", - "request": { - "method": "get", - "path": "/notification_rules" - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "notification_rules": [ - { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - } - ] - } - } - }, - { - "description": "a GET request for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", - "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51" - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "notification_rules": [ - { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - }, - { - "id": "20f182fc-6e32-4794-9007-97366d162c51", - "tags": [ - "physical" - ], - "regex_tags": [ - - ], - "entities": [ - "example.com" - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": true, - "critical_blackhole": true - } - ] - } - } - }, - { - "description": "a GET request for a single notification rule", - "provider_state": "no notification rule exists", - "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" - }, - "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find notification rules '05983623-fcef-42da-af44-ed6990b500fa'" - ] - } - } - }, - { - "description": "a GET request for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", - "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "notification_rules": [ - { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - } - ] - } - } - }, - { - "description": "a POST request with one set of pagerduty credentials", - "provider_state": "a contact with id 'abc' exists", - "request": { - "method": "post", - "path": "/contacts/abc/pagerduty_credentials", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "pagerduty_credentials": [ - { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" - } - ] - } - }, - "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "abc" - ] - } - }, - { - "description": "a POST request with one set of pagerduty credentials", - "provider_state": "no contact exists", - "request": { - "method": "post", - "path": "/contacts/abc/pagerduty_credentials", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "pagerduty_credentials": [ - { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" - } - ] - } - }, - "response": { - "status": 422, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "Contact id: 'abc' could not be loaded" - ] - } - } - }, - { - "description": "a PATCH request for pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", - "request": { - "method": "patch", - "path": "/pagerduty_credentials/abc", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/pagerduty_credentials/0/password", - "value": "pswrd" - } - ] - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for pagerduty credentials", - "provider_state": "no contact exists", - "request": { - "method": "patch", - "path": "/pagerduty_credentials/abc", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/pagerduty_credentials/0/password", - "value": "pswrd" - } - ] - }, - "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find contact 'abc'" - ] - } - } - }, - { - "description": "a PATCH request for pagerduty credentials", - "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", - "request": { - "method": "patch", - "path": "/pagerduty_credentials/abc,872", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/pagerduty_credentials/0/password", - "value": "pswrd" - } - ] - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for one set of pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", - "request": { - "method": "delete", - "path": "/pagerduty_credentials/abc", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for one set of pagerduty credentials", - "provider_state": "no contact exists", - "request": { - "method": "delete", - "path": "/pagerduty_credentials/abc", - "body": null - }, - "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find contact 'abc'" - ] - } - } - }, - { - "description": "a DELETE request for two sets of pagerduty credentials", - "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", - "request": { - "method": "delete", - "path": "/pagerduty_credentials/abc,872", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a GET request for all pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", - "request": { - "method": "get", - "path": "/pagerduty_credentials" - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "pagerduty_credentials": [ - { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" - } - ] - } - } - }, - { - "description": "a GET request for two sets of pagerduty credentials", - "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", - "request": { - "method": "get", - "path": "/pagerduty_credentials/abc,872" - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "pagerduty_credentials": [ - { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" - }, - { - "service_key": "mno", - "subdomain": "pqr", - "username": "stu", - "password": "vwx" - } - ] - } - } - }, - { - "description": "a GET request for one set of pagerduty credentials", - "provider_state": "no contact exists", - "request": { - "method": "get", - "path": "/pagerduty_credentials/abc" - }, - "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find contact 'abc'" - ] - } - } - }, - { - "description": "a GET request for one set of pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", - "request": { - "method": "get", - "path": "/pagerduty_credentials/abc" - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "pagerduty_credentials": [ - { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" - } - ] - } - } - }, - { - "description": "a GET request for a scheduled_maintenance report on a single check", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "get", - "path": "/scheduled_maintenance_report/checks/www.example.com:SSH" - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "scheduled_maintenance_reports": [ - { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } - ] - } - } - }, - { - "description": "a GET request for a downtime report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "get", - "path": "/downtime_report/entities" + "body": [ + { + "op": "replace", + "path": "/checks/0/enabled", + "value": false + } + ] }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "downtime_reports": [ - { - } - ] - } + "status": 204, + "body": "" } }, { @@ -1202,11 +535,12 @@ } }, { - "description": "a GET request for a downtime report on a single check", + "description": "a time limited GET request for a scheduled_maintenance report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/downtime_report/checks/www.example.com:SSH" + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH", + "query": "start_time=2014-09-26T14%3A45%3A21%2B09%3A30&end_time=2014-09-27T02%3A45%3A21%2B09%3A30" }, "response": { "status": 200, @@ -1214,19 +548,30 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ + "scheduled_maintenance_reports": [ { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } } }, { - "description": "a GET request for a outage report on a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a outage report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/outage_report/checks/www.example.com:SSH" + "path": "/outage_report/entities/1234,5678" }, "response": { "status": 200, @@ -1247,18 +592,31 @@ "www.example.com:SSH" ] } + }, + { + "outages": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } } }, { - "description": "a time limited GET request for a scheduled_maintenance report on all entities", + "description": "a time limited GET request for a outage report on one entity", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/scheduled_maintenance_report/entities", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "path": "/outage_report/entities/1234", + "query": "start_time=2014-09-26T14%3A45%3A21%2B09%3A30&end_time=2014-09-27T02%3A45%3A21%2B09%3A30" }, "response": { "status": 200, @@ -1266,9 +624,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "outage_reports": [ { - "scheduled_maintenances": [ + "outages": [ ], "links": { @@ -1285,12 +643,11 @@ } }, { - "description": "a time limited GET request for a scheduled_maintenance report on two entities", + "description": "a GET request for a unscheduled_maintenance report on two entities", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/scheduled_maintenance_report/entities/1234,5678", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "path": "/unscheduled_maintenance_report/entities/1234,5678" }, "response": { "status": 200, @@ -1298,9 +655,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "unscheduled_maintenance_reports": [ { - "scheduled_maintenances": [ + "unscheduled_maintenances": [ ], "links": { @@ -1313,7 +670,7 @@ } }, { - "scheduled_maintenances": [ + "unscheduled_maintenances": [ ], "links": { @@ -1330,44 +687,12 @@ } }, { - "description": "a time limited GET request for a unscheduled_maintenance report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/checks", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } - ] - } - } - }, - { - "description": "a time limited GET request for a outage report on one entity", + "description": "a time limited GET request for a outage report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/outage_report/entities/1234", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "path": "/outage_report/checks/www.example.com:SSH", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -1394,11 +719,11 @@ } }, { - "description": "a GET request for a outage report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a status report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/outage_report/checks" + "path": "/status_report/entities/1234,5678" }, "response": { "status": 200, @@ -1406,30 +731,22 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ + "status_reports": [ + { + }, { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } } ] } } }, { - "description": "a GET request for a outage report on two entities", + "description": "a time limited GET request for a scheduled_maintenance report on two entities", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/outage_report/entities/1234,5678" + "path": "/scheduled_maintenance_report/entities/1234,5678", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -1437,9 +754,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ + "scheduled_maintenance_reports": [ { - "outages": [ + "scheduled_maintenances": [ ], "links": { @@ -1452,7 +769,7 @@ } }, { - "outages": [ + "scheduled_maintenances": [ ], "links": { @@ -1469,11 +786,11 @@ } }, { - "description": "a GET request for a scheduled_maintenance report on all entities", + "description": "a GET request for a downtime report on all entities", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/scheduled_maintenance_report/entities" + "path": "/downtime_report/entities" }, "response": { "status": 200, @@ -1481,62 +798,37 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "downtime_reports": [ { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } } ] } } }, { - "description": "a time-limited GET request for a unscheduled_maintenance report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a unscheduled_maintenance report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "path": "/unscheduled_maintenance_report/entities/1234" }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "unscheduled_maintenance_reports": [ { "unscheduled_maintenances": [ ], "links": { "entity": [ - "5678" + "1234" ], "check": [ - "www2.example.com:PING" + "www.example.com:SSH" ] } } @@ -1545,12 +837,11 @@ } }, { - "description": "a time limited GET request for a downtime report on all checks", + "description": "a GET request for a outage report on all entities", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/downtime_report/checks", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "path": "/outage_report/entities" }, "response": { "status": 200, @@ -1558,19 +849,30 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ + "outage_reports": [ { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } } }, { - "description": "a GET request for a status report on two checks", + "description": "a GET request for a downtime report on two checks", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/status_report/checks/www.example.com:SSH,www2.example.com:PING" + "path": "/downtime_report/checks/www.example.com:SSH,www2.example.com:PING" }, "response": { "status": 200, @@ -1578,7 +880,7 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "status_reports": [ + "downtime_reports": [ { }, { @@ -1588,12 +890,11 @@ } }, { - "description": "a time limited GET request for a outage report on all entities", + "description": "a GET request for a scheduled_maintenance report on all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/outage_report/entities", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "path": "/scheduled_maintenance_report/checks" }, "response": { "status": 200, @@ -1601,9 +902,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ + "scheduled_maintenance_reports": [ { - "outages": [ + "scheduled_maintenances": [ ], "links": { @@ -1620,12 +921,11 @@ } }, { - "description": "a time limited GET request for a unscheduled_maintenance report on a single check", + "description": "a GET request for a outage report on all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "path": "/outage_report/checks" }, "response": { "status": 200, @@ -1633,9 +933,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenance_reports": [ + "outage_reports": [ { - "unscheduled_maintenances": [ + "outages": [ ], "links": { @@ -1652,11 +952,11 @@ } }, { - "description": "a GET request for a outage report on one entity", + "description": "a GET request for a unscheduled_maintenance report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/outage_report/entities/1234" + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -1664,9 +964,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ + "unscheduled_maintenance_reports": [ { - "outages": [ + "unscheduled_maintenances": [ ], "links": { @@ -1683,12 +983,12 @@ } }, { - "description": "a time limited GET request for a scheduled_maintenance report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a time limited GET request for a outage report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/scheduled_maintenance_report/checks", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "path": "/outage_report/entities/1234,5678", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -1696,9 +996,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "outage_reports": [ { - "scheduled_maintenances": [ + "outages": [ ], "links": { @@ -1709,18 +1009,31 @@ "www.example.com:SSH" ] } + }, + { + "outages": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } } }, { - "description": "a time limited GET request for a unscheduled_maintenance report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a time-limited GET request for a scheduled_maintenance report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/entities/1234", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -1728,9 +1041,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenance_reports": [ + "scheduled_maintenance_reports": [ { - "unscheduled_maintenances": [ + "scheduled_maintenances": [ ], "links": { @@ -1741,17 +1054,30 @@ "www.example.com:SSH" ] } + }, + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } } }, { - "description": "a GET request for a status report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a downtime report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/status_report/entities/1234,5678" + "path": "/downtime_report/entities/1234" }, "response": { "status": 200, @@ -1759,9 +1085,7 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "status_reports": [ - { - }, + "downtime_reports": [ { } ] @@ -1769,11 +1093,11 @@ } }, { - "description": "a GET request for a unscheduled_maintenance report on all checks", + "description": "a GET request for a scheduled_maintenance report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/checks" + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -1781,9 +1105,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenance_reports": [ + "scheduled_maintenance_reports": [ { - "unscheduled_maintenances": [ + "scheduled_maintenances": [ ], "links": { @@ -1800,12 +1124,12 @@ } }, { - "description": "a time-limited GET request for a outage report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a time limited GET request for a scheduled_maintenance report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/outage_report/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "path": "/scheduled_maintenance_report/checks", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -1813,9 +1137,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ + "scheduled_maintenance_reports": [ { - "outages": [ + "scheduled_maintenances": [ ], "links": { @@ -1826,31 +1150,38 @@ "www.example.com:SSH" ] } - }, + } + ] + } + } + }, + { + "description": "a GET request for a status report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/status_report/checks" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "status_reports": [ { - "outages": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } } ] } } }, { - "description": "a time limited GET request for a scheduled_maintenance report on one entity", + "description": "a time limited GET request for a outage report on all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/scheduled_maintenance_report/entities/1234", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "path": "/outage_report/checks", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -1858,9 +1189,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "outage_reports": [ { - "scheduled_maintenances": [ + "outages": [ ], "links": { @@ -1877,11 +1208,11 @@ } }, { - "description": "a GET request for a status report on a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a status report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/status_report/checks/www.example.com:SSH" + "path": "/status_report/checks/www.example.com:SSH,www2.example.com:PING" }, "response": { "status": 200, @@ -1890,6 +1221,8 @@ }, "body": { "status_reports": [ + { + }, { } ] @@ -1897,11 +1230,31 @@ } }, { - "description": "a GET request for a scheduled_maintenance report on two entities", + "description": "a GET request for a downtime report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/downtime_report/checks" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "downtime_reports": [ + { + } + ] + } + } + }, + { + "description": "a GET request for a outage report on two checks", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/scheduled_maintenance_report/entities/1234,5678" + "path": "/outage_report/checks/www.example.com:SSH,www2.example.com:PING" }, "response": { "status": 200, @@ -1909,9 +1262,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "outage_reports": [ { - "scheduled_maintenances": [ + "outages": [ ], "links": { @@ -1924,7 +1277,7 @@ } }, { - "scheduled_maintenances": [ + "outages": [ ], "links": { @@ -1941,12 +1294,12 @@ } }, { - "description": "a time limited GET request for a downtime report on a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a time-limited GET request for a outage report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/downtime_report/checks/www.example.com:SSH", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "path": "/outage_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -1954,19 +1307,43 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ + "outage_reports": [ + { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, { + "outages": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } } }, { - "description": "a GET request for a unscheduled_maintenance report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a scheduled_maintenance report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/entities" + "path": "/scheduled_maintenance_report/entities/1234,5678" }, "response": { "status": 200, @@ -1974,17 +1351,30 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenance_reports": [ + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, { - "unscheduled_maintenances": [ + "scheduled_maintenances": [ ], "links": { "entity": [ - "1234" + "5678" ], "check": [ - "www.example.com:SSH" + "www2.example.com:PING" ] } } @@ -1993,11 +1383,12 @@ } }, { - "description": "a GET request for a status report on one entity", + "description": "a time limited GET request for a downtime report on one entity", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/status_report/entities/1234" + "path": "/downtime_report/entities/1234", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -2005,7 +1396,7 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "status_reports": [ + "downtime_reports": [ { } ] @@ -2013,11 +1404,12 @@ } }, { - "description": "a GET request for a unscheduled_maintenance report on one entity", + "description": "a time limited GET request for a unscheduled_maintenance report on all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/entities/1234" + "path": "/unscheduled_maintenance_report/checks", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -2044,11 +1436,12 @@ } }, { - "description": "a GET request for a downtime report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a time limited GET request for a downtime report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/downtime_report/checks/www.example.com:SSH,www2.example.com:PING" + "path": "/downtime_report/checks", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -2057,8 +1450,6 @@ }, "body": { "downtime_reports": [ - { - }, { } ] @@ -2066,11 +1457,12 @@ } }, { - "description": "a GET request for a downtime report on one entity", + "description": "a time limited GET request for a unscheduled_maintenance report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/downtime_report/entities/1234" + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -2078,20 +1470,31 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ + "unscheduled_maintenance_reports": [ { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } } }, { - "description": "a time limited GET request for a downtime report on one entity", + "description": "a time limited GET request for a scheduled_maintenance report on one entity", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/downtime_report/entities/1234", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "path": "/scheduled_maintenance_report/entities/1234", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -2099,20 +1502,30 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ + "scheduled_maintenance_reports": [ { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } } }, { - "description": "a time limited GET request for a downtime report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a outage report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/downtime_report/entities/1234,5678", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "path": "/outage_report/entities/1234" }, "response": { "status": 200, @@ -2120,10 +1533,19 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ - { - }, + "outage_reports": [ { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } @@ -2135,7 +1557,7 @@ "request": { "method": "get", "path": "/unscheduled_maintenance_report/entities/1234,5678", - "query": "start_time=2014-09-26T14%3A24%3A22%2B09%3A30&end_time=2014-09-27T02%3A24%3A22%2B09%3A30" + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -2175,11 +1597,12 @@ } }, { - "description": "a GET request for a scheduled_maintenance report on one entity", + "description": "a time limited GET request for a downtime report on all entities", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/scheduled_maintenance_report/entities/1234" + "path": "/downtime_report/entities", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -2187,30 +1610,20 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "downtime_reports": [ { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } } ] } } }, { - "description": "a GET request for a unscheduled_maintenance report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a time limited GET request for a unscheduled_maintenance report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/entities/1234,5678" + "path": "/unscheduled_maintenance_report/entities/1234", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -2231,30 +1644,40 @@ "www.example.com:SSH" ] } + } + ] + } + } + }, + { + "description": "a time-limited GET request for a downtime report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "get", + "path": "/downtime_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "downtime_reports": [ + { }, { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } } ] } } }, { - "description": "a GET request for a outage report on all entities", + "description": "a GET request for a status report on one entity", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/outage_report/entities" + "path": "/status_report/entities/1234" }, "response": { "status": 200, @@ -2262,31 +1685,19 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ + "status_reports": [ { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } } ] } } }, { - "description": "a time-limited GET request for a scheduled_maintenance report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a unscheduled_maintenance report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/scheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + "path": "/unscheduled_maintenance_report/entities" }, "response": { "status": 200, @@ -2294,9 +1705,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "unscheduled_maintenance_reports": [ { - "scheduled_maintenances": [ + "unscheduled_maintenances": [ ], "links": { @@ -2307,31 +1718,18 @@ "www.example.com:SSH" ] } - }, - { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } } ] } } }, { - "description": "a time limited GET request for a downtime report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a time limited GET request for a downtime report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/downtime_report/entities", - "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + "path": "/downtime_report/entities/1234,5678", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -2340,6 +1738,8 @@ }, "body": { "downtime_reports": [ + { + }, { } ] @@ -2347,12 +1747,12 @@ } }, { - "description": "a time limited GET request for a scheduled_maintenance report on a single check", + "description": "a time limited GET request for a unscheduled_maintenance report on all entities", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/scheduled_maintenance_report/checks/www.example.com:SSH", - "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + "path": "/unscheduled_maintenance_report/entities", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -2360,9 +1760,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "unscheduled_maintenance_reports": [ { - "scheduled_maintenances": [ + "unscheduled_maintenances": [ ], "links": { @@ -2379,12 +1779,11 @@ } }, { - "description": "a time-limited GET request for a downtime report on two checks", + "description": "a GET request for a downtime report on two entities", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/downtime_report/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + "path": "/downtime_report/entities/1234,5678" }, "response": { "status": 200, @@ -2402,11 +1801,11 @@ } }, { - "description": "a GET request for a downtime report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a scheduled_maintenance report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/downtime_report/entities/1234,5678" + "path": "/scheduled_maintenance_report/entities" }, "response": { "status": 200, @@ -2414,22 +1813,62 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ + "scheduled_maintenance_reports": [ { - }, + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } + ] + } + } + }, + { + "description": "a GET request for a scheduled_maintenance report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/scheduled_maintenance_report/entities/1234" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "scheduled_maintenance_reports": [ { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } } }, { - "description": "a time limited GET request for a outage report on a single check", + "description": "a time limited GET request for a outage report on all entities", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/outage_report/checks/www.example.com:SSH", - "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + "path": "/outage_report/entities", + "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" }, "response": { "status": 200, @@ -2456,12 +1895,12 @@ } }, { - "description": "a time limited GET request for a outage report on all checks", + "description": "a time limited GET request for a scheduled_maintenance report on all entities", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/outage_report/checks", - "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + "path": "/scheduled_maintenance_report/entities", + "query": "start_time=2014-09-26T14%3A45%3A23%2B09%3A30&end_time=2014-09-27T02%3A45%3A23%2B09%3A30" }, "response": { "status": 200, @@ -2469,9 +1908,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ + "scheduled_maintenance_reports": [ { - "outages": [ + "scheduled_maintenances": [ ], "links": { @@ -2488,11 +1927,11 @@ } }, { - "description": "a GET request for a scheduled_maintenance report on all checks", + "description": "a GET request for a status report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/scheduled_maintenance_report/checks" + "path": "/status_report/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -2500,30 +1939,20 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "status_reports": [ { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } } ] } } }, { - "description": "a GET request for a unscheduled_maintenance report on two checks", + "description": "a time-limited GET request for a unscheduled_maintenance report on two checks", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING" + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-09-26T14%3A45%3A23%2B09%3A30&end_time=2014-09-27T02%3A45%3A23%2B09%3A30" }, "response": { "status": 200, @@ -2563,12 +1992,11 @@ } }, { - "description": "a time limited GET request for a outage report on two entities", + "description": "a GET request for a unscheduled_maintenance report on two checks", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/outage_report/entities/1234,5678", - "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING" }, "response": { "status": 200, @@ -2576,9 +2004,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ + "unscheduled_maintenance_reports": [ { - "outages": [ + "unscheduled_maintenances": [ ], "links": { @@ -2591,7 +2019,7 @@ } }, { - "outages": [ + "unscheduled_maintenances": [ ], "links": { @@ -2608,11 +2036,11 @@ } }, { - "description": "a GET request for a unscheduled_maintenance report on a single check", + "description": "a GET request for a outage report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH" + "path": "/outage_report/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -2620,9 +2048,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenance_reports": [ + "outage_reports": [ { - "unscheduled_maintenances": [ + "outages": [ ], "links": { @@ -2639,12 +2067,31 @@ } }, { - "description": "a time limited GET request for a unscheduled_maintenance report on all entities", + "description": "a GET request for a downtime report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/entities", - "query": "start_time=2014-09-26T14%3A24%3A23%2B09%3A30&end_time=2014-09-27T02%3A24%3A23%2B09%3A30" + "path": "/downtime_report/checks/www.example.com:SSH" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "downtime_reports": [ + { + } + ] + } + } + }, + { + "description": "a GET request for a unscheduled_maintenance report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/unscheduled_maintenance_report/checks" }, "response": { "status": 200, @@ -2671,31 +2118,231 @@ } }, { - "description": "a GET request for a status report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a status report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/status_report/entities" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "status_reports": [ + { + } + ] + } + } + }, + { + "description": "a time limited GET request for a downtime report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/downtime_report/checks/www.example.com:SSH", + "query": "start_time=2014-09-26T14%3A45%3A23%2B09%3A30&end_time=2014-09-27T02%3A45%3A23%2B09%3A30" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "downtime_reports": [ + { + } + ] + } + } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", + "request": { + "method": "delete", + "path": "/contacts/abc,872", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts 'abc'" + ] + } + } + }, + { + "description": "a POST request with one contact", + "provider_state": "no contact exists", + "request": { + "method": "post", + "path": "/contacts", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc" + ] + } + }, + { + "description": "a POST request with two contacts", + "provider_state": "no contact exists", + "request": { + "method": "post", + "path": "/contacts", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + }, + { + "id": "def", + "first_name": "Joan", + "last_name": "Smith", + "email": "joans@example.com" + } + ] + } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc", + "def" + ] + } + }, + { + "description": "a POST request with one contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "post", + "path": "/contacts", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] + } + ] + } + }, + "response": { + "status": 409, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "Contacts already exist with the following IDs: abc" + ] + } + } + }, + { + "description": "a GET request for a single contact", + "provider_state": "no contact exists", "request": { "method": "get", - "path": "/status_report/entities" + "path": "/contacts/abc" }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "status_reports": [ - { - } + "errors": [ + "could not find contacts 'abc'" ] } } }, { - "description": "a GET request for a status report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a single contact", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "get", - "path": "/status_report/checks" + "path": "/contacts/abc" }, "response": { "status": 200, @@ -2703,19 +2350,28 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "status_reports": [ + "contacts": [ { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] } ] } } }, { - "description": "a GET request for a outage report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for all contacts", + "provider_state": "no contact exists", "request": { "method": "get", - "path": "/outage_report/checks/www.example.com:SSH,www2.example.com:PING" + "path": "/contacts" }, "response": { "status": 200, @@ -2723,43 +2379,18 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ - { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - }, - { - "outages": [ + "contacts": [ - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } - } ] } } }, { - "description": "a GET request for a downtime report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for all contacts", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "get", - "path": "/downtime_report/checks" + "path": "/contacts" }, "response": { "status": 200, @@ -2767,29 +2398,38 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ + "contacts": [ { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC", + "tags": [ + "admin", + "night_shift" + ] } ] } } }, { - "description": "a POST request with one test notification", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a PATCH requestto change a link for a single contact", + "provider_state": "a contact with id '872' exists", "request": { - "method": "post", - "path": "/test_notifications/entities/1234,5678", + "method": "patch", + "path": "/contacts/872", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "test_notifications": [ - { - "summary": "testing" - } - ] - } + "body": [ + { + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" + } + ] }, "response": { "status": 204, @@ -2797,47 +2437,118 @@ } }, { - "description": "a POST request with one test notification", - "provider_state": "no entity exists", + "description": "a PATCH request to change properties for a single contact", + "provider_state": "no contact exists", "request": { - "method": "post", - "path": "/test_notifications/entities/1234", + "method": "patch", + "path": "/contacts/323", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "test_notifications": [ - { - "summary": "testing" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity '1234'" + "could not find contacts '323'" ] } } }, { - "description": "a POST request with two test notifications", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a PATCH request to change properties for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", + "request": { + "method": "patch", + "path": "/contacts/abc,872", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request to change links for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", + "request": { + "method": "patch", + "path": "/contacts/abc,872", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request to change properties for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "patch", + "path": "/contacts/abc", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "post", - "path": "/test_notifications/entities/1234", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "test_notifications": [ + "unscheduled_maintenances": [ { - "summary": "testing" + "duration": 3600, + "summary": "working" }, { - "summary": "more tests" + "duration": 3600, + "summary": "more work" } ] } @@ -2848,43 +2559,46 @@ } }, { - "description": "a POST request with one test notification", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "no check exists", "request": { "method": "post", - "path": "/test_notifications/entities/1234", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "test_notifications": [ + "unscheduled_maintenances": [ { - "summary": "testing" + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 204, - "body": "" + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { - "description": "a POST request with two test notifications", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "post", - "path": "/test_notifications/entities/1234,5678", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" - }, - "body": { - "test_notifications": [ - { - "summary": "testing" - }, + }, + "body": { + "unscheduled_maintenances": [ { - "summary": "more tests" + "duration": 3600, + "summary": "working" } ] } @@ -2895,18 +2609,23 @@ } }, { - "description": "a POST request with one test notification", + "description": "a POST request with two unscheduled maintenance periods", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH,www2.example.com:PING", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "test_notifications": [ + "unscheduled_maintenances": [ { - "summary": "testing" + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" } ] } @@ -2917,47 +2636,48 @@ } }, { - "description": "a POST request with one test notification", - "provider_state": "no check exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "test_notifications": [ + "unscheduled_maintenances": [ { - "summary": "testing" + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity 'www.example.com'" - ] - } + "status": 204, + "body": "" } }, { - "description": "a POST request with two test notifications", + "description": "a POST request with two scheduled maintenance periods", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "test_notifications": [ + "scheduled_maintenances": [ { - "summary": "testing" + "start_time": "2014-09-26T14:45:23+09:30", + "duration": 3600, + "summary": "working" }, { - "summary": "more tests" + "start_time": "2014-09-26T16:45:23+09:30", + "duration": 3600, + "summary": "more work" } ] } @@ -2968,43 +2688,48 @@ } }, { - "description": "a POST request with one test notification", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "no check exists", "request": { "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "test_notifications": [ + "scheduled_maintenances": [ { - "summary": "testing" + "start_time": "2014-09-26T14:45:23+09:30", + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 204, - "body": "" + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { - "description": "a POST request with two test notifications", + "description": "a POST request with one scheduled maintenance period", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH,www2.example.com:PING", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "test_notifications": [ - { - "summary": "testing" - }, + "scheduled_maintenances": [ { - "summary": "more tests" + "start_time": "2014-09-26T14:45:23+09:30", + "duration": 3600, + "summary": "working" } ] } @@ -3015,80 +2740,94 @@ } }, { - "description": "a POST request with one entity", - "provider_state": "no entity exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "post", - "path": "/entities", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "scheduled_maintenances": [ { - "name": "example.org", - "id": "57_example" + "start_time": "2014-09-26T14:45:23+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-26T16:45:23+09:30", + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "57_example" - ] + "status": 204, + "body": "" } }, { - "description": "a POST request with two entities", - "provider_state": "no entity exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "post", - "path": "/entities", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ - { - "name": "example.org", - "id": "57_example" - }, + "scheduled_maintenances": [ { - "name": "example2.org", - "id": "58" + "start_time": "2014-09-26T14:45:23+09:30", + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 201, + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, "body": [ - "57_example", - "58" + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T14:45:23+09:30" + } ] + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a PATCH request for a single entity", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "patch", - "path": "/entities/1234", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T14:45:23+09:30" } ] }, @@ -3098,450 +2837,371 @@ } }, { - "description": "a PATCH request for a single entity", - "provider_state": "no entity exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no check exists", "request": { "method": "patch", - "path": "/entities/1234", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T14:45:23+09:30" } ] }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find entity '1234'" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a GET request for all entities", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/entities" + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-26T14%3A45%3A23%2B09%3A30" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "entities": [ - { - "name": "www.example.com", - "id": "1234" - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a GET request for all entities", - "provider_state": "no entity exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "get", - "path": "/entities" + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-09-26T14%3A45%3A23%2B09%3A30" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no check exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-09-26T14%3A45%3A23%2B09%3A30" + }, + "response": { + "status": 404, "body": { - "entities": [ - + "errors": [ + "could not find entity 'www.example.com'" ] } } }, { - "description": "a GET request for a single entity", + "description": "a POST request with two unscheduled maintenance periods", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/entities/1234" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "unscheduled_maintenances": [ { - "name": "www.example.com", - "id": "1234" + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a single entity", + "description": "a POST request with one unscheduled maintenance period", "provider_state": "no entity exists", "request": { - "method": "get", - "path": "/entities/1234" + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find entities: '1234'" + "could not find entity '1234'" ] } } }, { - "description": "a POST request with one check", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/checks", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "unscheduled_maintenances": [ { - "name": "SSH", - "entity_id": "1234" + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "www.example.com:SSH" - ] + "status": 204, + "body": "" } }, { - "description": "a POST request with two checks", + "description": "a POST request with two unscheduled maintenance periods", "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/checks", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "unscheduled_maintenances": [ { - "name": "SSH", - "entity_id": "1234" + "duration": 3600, + "summary": "working" }, { - "name": "PING", - "entity_id": "5678" + "duration": 3600, + "summary": "more work" } ] } }, - "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "www.example.com:SSH", - "www2.example.com:PING" - ] - } - }, - { - "description": "a PATCH request for a single check", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "patch", - "path": "/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/checks/0/enabled", - "value": false - } - ] - }, "response": { "status": 204, "body": "" } }, { - "description": "a PATCH request for a single check", - "provider_state": "no entity exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "patch", - "path": "/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/checks/0/enabled", - "value": false - } - ] - }, - "response": { - "status": 404, + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find entity 'www.example.com'" + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } ] } - } - }, - { - "description": "a GET request for all checks", - "provider_state": "no entity exists", - "request": { - "method": "get", - "path": "/checks" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "checks": [ - - ] - } + "status": 204, + "body": "" } }, { - "description": "a GET request for all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/checks" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "scheduled_maintenances": [ { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } + "start_time": "2014-09-26T14:45:24+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-26T16:45:24+09:30", + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "no entity exists", "request": { - "method": "get", - "path": "/checks/www.example.com:SSH" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "checks": [ + "scheduled_maintenances": [ { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } + "start_time": "2014-09-26T14:45:24+09:30", + "duration": 3600, + "summary": "working" } ] } - } - }, - { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "no entity exists", - "request": { - "method": "get", - "path": "/checks/www.example.com:SSH" }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find entity checks: 'www.example.com:SSH'" + "could not find entity '1234'" ] } } }, { - "description": "a POST request with one contact", - "provider_state": "no contact exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/contacts", + "path": "/scheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "scheduled_maintenances": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "start_time": "2014-09-26T14:45:24+09:30", + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "abc" - ] + "status": 204, + "body": "" } }, { - "description": "a POST request with one contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/contacts", + "path": "/scheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "scheduled_maintenances": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] - } - ] - } - }, - "response": { - "status": 409, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "Contacts already exist with the following IDs: abc" + "start_time": "2014-09-26T14:45:24+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-09-26T16:45:24+09:30", + "duration": 3600, + "summary": "more work" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a POST request with two contacts", - "provider_state": "no contact exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/contacts", + "path": "/scheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ - { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] - }, + "scheduled_maintenances": [ { - "id": "def", - "first_name": "Joan", - "last_name": "Smith", - "email": "joans@example.com" + "start_time": "2014-09-26T14:45:24+09:30", + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 201, + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, "body": [ - "abc", - "def" + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T14:45:24+09:30" + } ] + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a PATCH request to change properties for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "patch", - "path": "/contacts/abc,872", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T14:45:24+09:30" } ] }, @@ -3551,50 +3211,38 @@ } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "no contact exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no entity exists", "request": { "method": "patch", - "path": "/contacts/323", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-09-26T14:45:24+09:30" } ] }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find contacts '323'" + "could not find entity '1234'" ] } } }, { - "description": "a PATCH requestto change a link for a single contact", - "provider_state": "a contact with id '872' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "patch", - "path": "/contacts/872", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" - } - ] + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-26T14%3A45%3A24%2B09%3A30" }, "response": { "status": 204, @@ -3602,21 +3250,12 @@ } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "patch", - "path": "/contacts/abc", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] + "method": "delete", + "path": "/scheduled_maintenances/entities/1234,5678", + "query": "start_time=2014-09-26T14%3A45%3A24%2B09%3A30" }, "response": { "status": 204, @@ -3624,21 +3263,29 @@ } }, { - "description": "a PATCH request to change links for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no entity exists", "request": { - "method": "patch", - "path": "/contacts/abc,872", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" - } - ] + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-09-26T14%3A45%3A24%2B09%3A30" + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } + } + }, + { + "description": "a DELETE request for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "request": { + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "body": null }, "response": { "status": 204, @@ -3646,11 +3293,11 @@ } }, { - "description": "a DELETE request for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a DELETE request for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { "method": "delete", - "path": "/contacts/abc", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", "body": null }, "response": { @@ -3659,11 +3306,11 @@ } }, { - "description": "a DELETE request for a single contact", - "provider_state": "no contact exists", + "description": "a DELETE request for a single notification rule", + "provider_state": "no notification rule exists", "request": { "method": "delete", - "path": "/contacts/abc", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", "body": null }, "response": { @@ -3673,107 +3320,183 @@ }, "body": { "errors": [ - "could not find contacts 'abc'" + "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a DELETE request for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a POST request with one notification rule", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "delete", - "path": "/contacts/abc,872", - "body": null + "method": "post", + "path": "/contacts/abc/notification_rules", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "notification_rules": [ + { + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + } + ] + } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + { + "json_class": "Pact::Term", + "data": { + "generate": "05983623-fcef-42da-af44-ed6990b500fa", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + } + ] } }, { - "description": "a GET request for all contacts", + "description": "a POST request with two notification rules", "provider_state": "a contact with id 'abc' exists", "request": { - "method": "get", - "path": "/contacts" + "method": "post", + "path": "/contacts/abc/notification_rules", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "notification_rules": [ + { + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + }, + { + "entity_tags": null, + "entities": [ + "foo-app-02.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": true, + "critical_blackhole": false + } + ] + } }, "response": { - "status": 200, + "status": 201, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": { - "contacts": [ - { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "body": [ + { + "json_class": "Pact::Term", + "data": { + "generate": "05983623-fcef-42da-af44-ed6990b500fa", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} } - ] - } + }, + { + "json_class": "Pact::Term", + "data": { + "generate": "20f182fc-6e32-4794-9007-97366d162c51", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + } + ] } }, { - "description": "a GET request for all contacts", + "description": "a POST request with one notification rule", "provider_state": "no contact exists", "request": { - "method": "get", - "path": "/contacts" - }, - "response": { - "status": 200, + "method": "post", + "path": "/contacts/abc/notification_rules", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ - + "notification_rules": [ + { + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + } ] } - } - }, - { - "description": "a GET request for a single contact", - "provider_state": "a contact with id 'abc' exists", - "request": { - "method": "get", - "path": "/contacts/abc" }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "contacts": [ - { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] - } + "errors": [ + "could not find contact 'abc'" ] } } }, { - "description": "a GET request for a single contact", - "provider_state": "no contact exists", + "description": "a GET request for a single notification rule", + "provider_state": "no notification rule exists", "request": { "method": "get", - "path": "/contacts/abc" + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" }, "response": { "status": 404, @@ -3782,139 +3505,189 @@ }, "body": { "errors": [ - "could not find contacts 'abc'" + "could not find notification rules '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for all notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-26T14:24:24+09:30", - "duration": 3600, - "summary": "working" - } - ] - } + "method": "get", + "path": "/notification_rules" }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "no entity exists", - "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "notification_rules": [ { - "start_time": "2014-09-26T14:24:24+09:30", - "duration": 3600, - "summary": "working" + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "method": "get", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-26T14:24:24+09:30", - "duration": 3600, - "summary": "working" - }, + "notification_rules": [ { - "start_time": "2014-09-26T16:24:24+09:30", - "duration": 3600, - "summary": "more work" + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "method": "get", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "notification_rules": [ + { + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + }, { - "start_time": "2014-09-26T14:24:24+09:30", - "duration": 3600, - "summary": "working" + "id": "20f182fc-6e32-4794-9007-97366d162c51", + "tags": [ + "physical" + ], + "regex_tags": [ + + ], + "entities": [ + "example.com" + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": true, + "critical_blackhole": true } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a PATCH request to change properties for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "method": "patch", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-26T14:24:24+09:30", - "duration": 3600, - "summary": "working" - }, - { - "start_time": "2014-09-26T16:24:24+09:30", - "duration": 3600, - "summary": "more work" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] }, "response": { "status": 204, @@ -3922,22 +3695,21 @@ } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a PATCH request to change properties for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "method": "patch", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] }, "response": { "status": 204, @@ -3945,193 +3717,199 @@ } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "no entity exists", + "description": "a PATCH request to change properties for a single notification rule", + "provider_state": "no notification rule exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "method": "patch", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity '1234'" + "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with two entities", + "provider_state": "no entity exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "path": "/entities", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "entities": [ { - "duration": 3600, - "summary": "working" + "name": "example.org", + "id": "57_example" }, { - "duration": 3600, - "summary": "more work" + "name": "example2.org", + "id": "58" } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example", + "58" + ] } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with one entity", + "provider_state": "no entity exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "path": "/entities", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "entities": [ { - "duration": 3600, - "summary": "working" + "name": "example.org", + "id": "57_example" } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example" + ] } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for a single entity", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "method": "get", + "path": "/entities/1234" + }, + "response": { + "status": 404, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, - { - "duration": 3600, - "summary": "more work" - } + "errors": [ + "could not find entities: '1234'" ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a DELETE request for a scheduled maintenance period", + "description": "a GET request for a single entity", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-26T14%3A24%3A24%2B09%3A30" + "method": "get", + "path": "/entities/1234" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "entities": [ + { + "name": "www.example.com", + "id": "1234" + } + ] + } } }, { - "description": "a DELETE request for a scheduled maintenance period", + "description": "a GET request for all entities", "provider_state": "no entity exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-26T14%3A24%3A24%2B09%3A30" + "method": "get", + "path": "/entities" }, "response": { - "status": 404, + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { - "errors": [ - "could not find entity '1234'" + "entities": [ + ] } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234,5678", - "query": "start_time=2014-09-26T14%3A24%3A24%2B09%3A30" - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", - "request": { - "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T14:24:24+09:30" - } - ] + "description": "a GET request for all entities", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "get", + "path": "/entities" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "entities": [ + { + "name": "www.example.com", + "id": "1234" + } + ] + } } }, { - "description": "a PATCH request for an unscheduled maintenance period", + "description": "a PATCH request for a single entity", "provider_state": "no entity exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", + "path": "/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T14:24:24+09:30" + "path": "/entities/0/name", + "value": "example3.com" } ] }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ "could not find entity '1234'" @@ -4140,19 +3918,19 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a PATCH request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/entities/1234,5678", + "path": "/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T14:24:24+09:30" + "path": "/entities/0/name", + "value": "example3.com" } ] }, @@ -4162,20 +3940,21 @@ } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a POST request with two test notifications", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "path": "/test_notifications/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "test_notifications": [ { - "start_time": "2014-09-26T14:24:24+09:30", - "duration": 3600, - "summary": "working" + "summary": "testing" + }, + { + "summary": "more tests" } ] } @@ -4186,20 +3965,18 @@ } }, { - "description": "a POST request with one scheduled maintenance period", + "description": "a POST request with one test notification", "provider_state": "no check exists", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "path": "/test_notifications/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "test_notifications": [ { - "start_time": "2014-09-26T14:24:24+09:30", - "duration": 3600, - "summary": "working" + "summary": "testing" } ] } @@ -4214,25 +3991,43 @@ } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one test notification", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "path": "/test_notifications/checks/www.example.com:SSH,www2.example.com:PING", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "test_notifications": [ { - "start_time": "2014-09-26T14:24:24+09:30", - "duration": 3600, - "summary": "working" + "summary": "testing" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two test notifications", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH,www2.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" }, { - "start_time": "2014-09-26T16:24:24+09:30", - "duration": 3600, - "summary": "more work" + "summary": "more tests" } ] } @@ -4243,20 +4038,18 @@ } }, { - "description": "a POST request with one scheduled maintenance period", + "description": "a POST request with one test notification", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "path": "/test_notifications/checks/www.example.com:SSH", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "test_notifications": [ { - "start_time": "2014-09-26T14:24:24+09:30", - "duration": 3600, - "summary": "working" + "summary": "testing" } ] } @@ -4267,25 +4060,21 @@ } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a POST request with two test notifications", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "path": "/test_notifications/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "test_notifications": [ { - "start_time": "2014-09-26T14:24:24+09:30", - "duration": 3600, - "summary": "working" + "summary": "testing" }, { - "start_time": "2014-09-26T16:24:24+09:30", - "duration": 3600, - "summary": "more work" + "summary": "more tests" } ] } @@ -4296,19 +4085,44 @@ } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a POST request with one test notification", + "provider_state": "no entity exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "path": "/test_notifications/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "test_notifications": [ { - "duration": 3600, - "summary": "working" + "summary": "testing" + } + ] + } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } + } + }, + { + "description": "a POST request with one test notification", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/test_notifications/entities/1234,5678", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" } ] } @@ -4319,166 +4133,344 @@ } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "no check exists", + "description": "a POST request with two test notifications", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/test_notifications/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "test_notifications": [ { - "duration": 3600, - "summary": "working" + "summary": "testing" + }, + { + "summary": "more tests" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one test notification", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "post", + "path": "/test_notifications/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" } ] } }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for one medium", + "provider_state": "a contact with id 'abc' has email and sms media", + "request": { + "method": "delete", + "path": "/media/abc_email", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for two media", + "provider_state": "a contact with id 'abc' has email and sms media", + "request": { + "method": "delete", + "path": "/media/abc_email,abc_sms", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for one medium", + "provider_state": "no contact exists", + "request": { + "method": "delete", + "path": "/media/abc_email", + "body": null + }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find contact 'abc'" + ] + } + } + }, + { + "description": "a POST request with one medium", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "post", + "path": "/contacts/abc/media", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "media": [ + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 + } ] } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc_sms" + ] } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with two media", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/contacts/abc/media", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "media": [ { - "duration": 3600, - "summary": "working" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 }, { - "duration": 3600, - "summary": "more work" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3 } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc_sms", + "abc_email" + ] } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one medium", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/contacts/abc/media", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenances": [ + "media": [ { - "duration": 3600, - "summary": "working" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 } ] } }, "response": { - "status": 204, - "body": "" + "status": 422, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "Contact id: 'abc' could not be loaded" + ] + } } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for sms media", + "provider_state": "no contact exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "method": "get", + "path": "/media/abc_sms" + }, + "response": { + "status": 404, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, - { - "duration": 3600, - "summary": "more work" - } + "errors": [ + "could not find contact 'abc'" ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for all media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-26T14%3A24%3A25%2B09%3A30" + "method": "get", + "path": "/media" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "media": [ + { + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3, + "links": { + "contacts": [ + "abc" + ] + } + }, + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } + } + ] + } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no check exists", + "description": "a GET request for sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-26T14%3A24%3A25%2B09%3A30" + "method": "get", + "path": "/media/abc_sms" }, "response": { - "status": 404, + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { - "errors": [ - "could not find entity 'www.example.com'" + "media": [ + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } + } ] } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-09-26T14%3A24%3A25%2B09%3A30" + "method": "get", + "path": "/media/abc_email,abc_sms" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "media": [ + { + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3, + "links": { + "contacts": [ + "abc" + ] + } + }, + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } + } + ] + } } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request for email media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/media/abc_email", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T14:24:25+09:30" + "path": "/media/0/interval", + "value": 50 + }, + { + "op": "replace", + "path": "/media/0/rollup_threshold", + "value": 3 } ] }, @@ -4488,51 +4480,59 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no check exists", + "description": "a PATCH request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/media/abc_email,abc_sms", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T14:24:25+09:30" + "path": "/media/0/interval", + "value": 50 + }, + { + "op": "replace", + "path": "/media/0/rollup_threshold", + "value": 3 } ] }, "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity 'www.example.com'" - ] - } + "status": 204, + "body": "" } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a PATCH request for email media", + "provider_state": "no contact exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "path": "/media/abc_email", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T14:24:25+09:30" + "path": "/media/0/interval", + "value": 50 } ] }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contact 'abc'" + ] + } } } ], From 383a981ba35acf5640c1417dd895726a464a2a88 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Thu, 2 Oct 2014 15:18:05 +0930 Subject: [PATCH 22/69] cleanup mirror logic, untested --- lib/flapjack/cli/receiver.rb | 83 +++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index 781d06cd2..c5215900c 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -328,23 +328,16 @@ def json_feeder(opts = {}) puts "Done." end - def mirror_receive(opts) unless opts[:follow] || opts[:all] exit_now! "one or both of --follow or --all is required" end - source_redis = Redis.new(:url => opts[:source]) - - # refresh the key name cache, avoid repeated calls to redis KEYS - # this cache will be updated any time a new archive bucket is created - archive_keys = source_redis.keys("events_archive:*").group_by do |ak| - (source_redis.scard(ak) > 0) ? 't' : 'f' - end + source_addr = opts[:source] - source_redis.srem('known_events_archive_keys', archive_keys['f']) unless archive_keys['f'].empty? - source_redis.sadd('known_events_archive_keys', archive_keys['t']) unless archive_keys['t'].empty? + source_redis = Redis.new(:url => source_addr) + refresh_archive_index(source_addr, :redis => source_redis) archives = mirror_get_archive_keys_stats(source_redis) raise "found no archives!" if archives.empty? @@ -359,57 +352,69 @@ def mirror_receive(opts) events_sent = 0 case when opts[:all] - archive_key = archives[0][:name] + archive_idx = 0 cursor = -1 when opts[:last], opts[:time] raise "Sorry, unimplemented" else # wait for the next event to be archived, so point the cursor at a non-existant # slot in the list, the one before the 0'th - archive_key = archives[-1][:name] + archive_idx = archives.size - 1 cursor = -1 - archives[-1][:size] end + archive_key = archives[archive_idx][:name] puts archive_key loop do - new_archive_key = false - # something to read at cursor? event = source_redis.lindex(archive_key, cursor) if event Flapjack::Data::Event.add(event, :redis => redis) events_sent += 1 print "#{events_sent} " if events_sent % 1000 == 0 cursor -= 1 - else - puts "\narchive key: #{archive_key}, cursor: #{cursor}" - # do we need to look at the next archive bucket? - archives = mirror_get_archive_keys_stats(source_redis) - - unless archives.empty? - i = archives.index {|a| a[:name] == archive_key } || 0 - - if ((archives[i][:size] == (cursor.abs + 1)) || (archives[i][:size] == 0)) - if archives[i + 1].nil? - return unless opts[:follow] - else - archive_key = archives[i + 1][:name] - puts archive_key - cursor = -1 - new_archive_key = true - end - end - end - sleep 1 unless new_archive_key + next + end + + archives = mirror_get_archive_keys_stats(source_addr, :redis => source_redis) + + if archives.any? {|a| a[:size] == 0} + # data may be out of date -- refresh, then reject any immediately + # expired keys directly; don't keep chasing updated data + refresh_archive_index(source_addr, :redis => source_redis) + archives = mirror_get_archive_keys_stats(source_addr, :redis => source_redis).select {|a| a[:size] > 0} end + + if archives.empty? + sleep 1 + next + end + + archive_idx = archives.index {|a| a[:name] == archive_key } + archive_idx = archive_idx.nil? ? 0 : (archive_idx + 1) + archive_key = archives[archive_idx][:name] + puts archive_key + cursor = -1 + end + end + + def mirror_get_archive_keys_stats(name, opts = {}) + source_redis = opts[:redis] + redis.smembers("known_events_archive_keys:#{name}").sort.collect do |eak| + {:name => eak, :size => source_redis.llen(eak)} end end - def mirror_get_archive_keys_stats(source_redis) - source_redis.smembers('known_events_archive_keys').sort.map {|eak| - { :name => eak, - :size => source_redis.llen(eak) } - } + def refresh_archive_index(name, opts = {}) + source_redis = opts[:redis] + # refresh the key name cache, avoid repeated calls to redis KEYS + # this cache will be updated any time a new archive bucket is created + archive_keys = source_redis.keys("events_archive:*").group_by do |ak| + (source_redis.scard(ak) > 0) ? 't' : 'f' + end + + redis.srem("known_events_archive_keys:#{name}", archive_keys['f']) unless archive_keys['f'].empty? + redis.sadd("known_events_archive_keys:#{name}", archive_keys['t']) unless archive_keys['t'].empty? end end From e9b9cc13879e570fe77acaf937f3cfeb48109a9a Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Thu, 2 Oct 2014 16:04:39 +0930 Subject: [PATCH 23/69] pass through client-generated UUID for edit_contacts --- lib/flapjack/gateways/web/public/js/backbone.jsonapi.js | 5 +++++ lib/flapjack/gateways/web/public/js/flapjack.js | 6 +++++- lib/flapjack/gateways/web/public/js/modules/contact.js | 3 +-- lib/flapjack/gateways/web/public/js/self_stats.js | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js b/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js index 2742cf0b9..e4d533bff 100644 --- a/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +++ b/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js @@ -46,6 +46,11 @@ toolbox.batchRequest = function(klass, ids, amount, success) { Backbone.JSONAPIModel = Backbone.Model.extend({ + isNew: function() { + return( !_.isUndefined(this.persisted) && !_.isUndefined(this.persisted) + && (this.persisted == false)); + }, + // the following two methods, and batchRequest, should be folded into // Collection.fetch (and Model.fetch?) resolveLink: function(name, klass, superset) { diff --git a/lib/flapjack/gateways/web/public/js/flapjack.js b/lib/flapjack/gateways/web/public/js/flapjack.js index 1ff53a0c4..95cc9ac8f 100644 --- a/lib/flapjack/gateways/web/public/js/flapjack.js +++ b/lib/flapjack/gateways/web/public/js/flapjack.js @@ -44,7 +44,11 @@ $(document).ready(function() { // skip if modal showing if ( $('#contactModal').hasClass('in') ) { return; } - var contactDetailsView = new (Contact.Views.ContactDetails)({model: new (Contact.Model)()}); + var contact = new (Contact.Model)(); + contact.persisted = false; + contact.set('id', toolbox.generateUUID()); + + var contactDetailsView = new (Contact.Views.ContactDetails)({model: contact}); contactDetailsView.render(); $('div.modal-dialog').append(contactDetailsView.$el); diff --git a/lib/flapjack/gateways/web/public/js/modules/contact.js b/lib/flapjack/gateways/web/public/js/modules/contact.js index 69a4eeb66..2b08f1d58 100644 --- a/lib/flapjack/gateways/web/public/js/modules/contact.js +++ b/lib/flapjack/gateways/web/public/js/modules/contact.js @@ -55,8 +55,7 @@ tagName: 'tbody', id: 'contactList', initialize: function() { - // FIXME: #619 dirty fix... - this.collection.on('add', location.reload, location); + this.collection.on('add', this.render, this); this.collection.on('remove', this.render, this); }, render: function() { diff --git a/lib/flapjack/gateways/web/public/js/self_stats.js b/lib/flapjack/gateways/web/public/js/self_stats.js index a83ffe54e..eda88eed7 100644 --- a/lib/flapjack/gateways/web/public/js/self_stats.js +++ b/lib/flapjack/gateways/web/public/js/self_stats.js @@ -66,7 +66,7 @@ $(document).ready(function() { var d = new Date().getTime(); var value = {x: d, y: json.event_queue_length} data[0].values.push(value); - console.log(data[0].values.length); + // console.log(data[0].values.length); // Remove old data, to keep the graph performant if (data[0].values.length > 100) { From 1c63049257a8aa4a352ef661a3d21b74bc125eea Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Thu, 2 Oct 2014 21:18:16 +0930 Subject: [PATCH 24/69] update diner pact --- .../pacts/flapjack-diner_v1.0.json | 4410 ++++++++--------- 1 file changed, 2195 insertions(+), 2215 deletions(-) diff --git a/spec/service_consumers/pacts/flapjack-diner_v1.0.json b/spec/service_consumers/pacts/flapjack-diner_v1.0.json index 77ca3414c..d3ec2c617 100644 --- a/spec/service_consumers/pacts/flapjack-diner_v1.0.json +++ b/spec/service_consumers/pacts/flapjack-diner_v1.0.json @@ -7,138 +7,180 @@ }, "interactions": [ { - "description": "a DELETE request for one set of pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", - "request": { - "method": "delete", - "path": "/pagerduty_credentials/abc", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for two sets of pagerduty credentials", - "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", + "description": "a GET request for a downtime report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "delete", - "path": "/pagerduty_credentials/abc,872", - "body": null + "method": "get", + "path": "/downtime_report/checks" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "downtime_reports": [ + { + } + ] + } } }, { - "description": "a DELETE request for one set of pagerduty credentials", - "provider_state": "no contact exists", + "description": "a GET request for a outage report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "delete", - "path": "/pagerduty_credentials/abc", - "body": null + "method": "get", + "path": "/outage_report/entities/1234" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find contact 'abc'" + "outage_reports": [ + { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } ] } } }, { - "description": "a POST request with one set of pagerduty credentials", - "provider_state": "no contact exists", + "description": "a time limited GET request for a downtime report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/contacts/abc/pagerduty_credentials", + "method": "get", + "path": "/downtime_report/entities", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "pagerduty_credentials": [ + "downtime_reports": [ { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" } ] } + } + }, + { + "description": "a GET request for a scheduled_maintenance report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "get", + "path": "/scheduled_maintenance_report/entities/1234,5678" }, "response": { - "status": 422, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "Contact id: 'abc' could not be loaded" + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } + } ] } } }, { - "description": "a POST request with one set of pagerduty credentials", - "provider_state": "a contact with id 'abc' exists", + "description": "a time limited GET request for a downtime report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/contacts/abc/pagerduty_credentials", + "method": "get", + "path": "/downtime_report/checks", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "pagerduty_credentials": [ + "downtime_reports": [ { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" } ] } - }, - "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "abc" - ] } }, { - "description": "a GET request for one set of pagerduty credentials", - "provider_state": "no contact exists", + "description": "a time limited GET request for a scheduled_maintenance report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/pagerduty_credentials/abc" + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find contact 'abc'" + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } ] } } }, { - "description": "a GET request for all pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", + "description": "a GET request for a unscheduled_maintenance report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/pagerduty_credentials" + "path": "/unscheduled_maintenance_report/entities/1234" }, "response": { "status": 200, @@ -146,23 +188,31 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "pagerduty_credentials": [ + "unscheduled_maintenance_reports": [ { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } } }, { - "description": "a GET request for one set of pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", + "description": "a time limited GET request for a outage report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/pagerduty_credentials/abc" + "path": "/outage_report/checks", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { "status": 200, @@ -170,23 +220,31 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "pagerduty_credentials": [ + "outage_reports": [ { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } } }, { - "description": "a GET request for two sets of pagerduty credentials", - "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", + "description": "a time limited GET request for a unscheduled_maintenance report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/pagerduty_credentials/abc,872" + "path": "/unscheduled_maintenance_report/entities/1234,5678", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { "status": 200, @@ -194,182 +252,165 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "pagerduty_credentials": [ + "unscheduled_maintenance_reports": [ { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } }, { - "service_key": "mno", - "subdomain": "pqr", - "username": "stu", - "password": "vwx" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } } }, { - "description": "a PATCH request for pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", - "request": { - "method": "patch", - "path": "/pagerduty_credentials/abc", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/pagerduty_credentials/0/password", - "value": "pswrd" - } - ] - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for pagerduty credentials", - "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", - "request": { - "method": "patch", - "path": "/pagerduty_credentials/abc,872", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/pagerduty_credentials/0/password", - "value": "pswrd" - } - ] - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for pagerduty credentials", - "provider_state": "no contact exists", + "description": "a GET request for a scheduled_maintenance report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "patch", - "path": "/pagerduty_credentials/abc", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/pagerduty_credentials/0/password", - "value": "pswrd" - } - ] + "method": "get", + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find contact 'abc'" - ] - } - } - }, - { - "description": "a POST request with two checks", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", - "request": { - "method": "post", - "path": "/checks", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "checks": [ + "scheduled_maintenance_reports": [ { - "name": "SSH", - "entity_id": "1234" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } }, { - "name": "PING", - "entity_id": "5678" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } - }, - "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "www.example.com:SSH", - "www2.example.com:PING" - ] } }, { - "description": "a POST request with one check", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a time-limited GET request for a unscheduled_maintenance report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/checks", + "method": "get", + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ + "unscheduled_maintenance_reports": [ { - "name": "SSH", - "entity_id": "1234" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } - }, - "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "www.example.com:SSH" - ] } }, { - "description": "a GET request for check 'www.example.com:SSH'", - "provider_state": "no entity exists", + "description": "a time limited GET request for a unscheduled_maintenance report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/checks/www.example.com:SSH" + "path": "/unscheduled_maintenance_report/entities/1234", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find entity checks: 'www.example.com:SSH'" + "unscheduled_maintenance_reports": [ + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } ] } } }, { - "description": "a GET request for check 'www.example.com:SSH'", + "description": "a time limited GET request for a outage report on one entity", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/checks/www.example.com:SSH" + "path": "/outage_report/entities/1234", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { "status": 200, @@ -377,14 +418,17 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ + "outage_reports": [ { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", + "outages": [ + + ], "links": { - "entities": [ + "entity": [ "1234" + ], + "check": [ + "www.example.com:SSH" ] } } @@ -393,11 +437,11 @@ } }, { - "description": "a GET request for all checks", + "description": "a GET request for a status report on all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/checks" + "path": "/status_report/checks" }, "response": { "status": 200, @@ -405,27 +449,19 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ + "status_reports": [ { - "id": "www.example.com:SSH", - "name": "SSH", - "entity_name": "www.example.com", - "links": { - "entities": [ - "1234" - ] - } } ] } } }, { - "description": "a GET request for all checks", - "provider_state": "no entity exists", + "description": "a GET request for a downtime report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/checks" + "path": "/downtime_report/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -433,69 +469,41 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ - + "downtime_reports": [ + { + } ] } } }, { - "description": "a PATCH request for a single check", - "provider_state": "no entity exists", + "description": "a GET request for a status report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "patch", - "path": "/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/checks/0/enabled", - "value": false - } - ] + "method": "get", + "path": "/status_report/checks/www.example.com:SSH,www2.example.com:PING" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find entity 'www.example.com'" - ] + "status_reports": [ + { + }, + { + } + ] } } }, { - "description": "a PATCH request for a single check", + "description": "a GET request for a scheduled_maintenance report on one entity", "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "patch", - "path": "/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/checks/0/enabled", - "value": false - } - ] - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a GET request for a scheduled_maintenance report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/scheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING" + "path": "/scheduled_maintenance_report/entities/1234" }, "response": { "status": 200, @@ -516,31 +524,18 @@ "www.example.com:SSH" ] } - }, - { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } } ] } } }, { - "description": "a time limited GET request for a scheduled_maintenance report on a single check", + "description": "a time limited GET request for a scheduled_maintenance report on all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/scheduled_maintenance_report/checks/www.example.com:SSH", - "query": "start_time=2014-09-26T14%3A45%3A21%2B09%3A30&end_time=2014-09-27T02%3A45%3A21%2B09%3A30" + "path": "/scheduled_maintenance_report/checks", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { "status": 200, @@ -567,11 +562,12 @@ } }, { - "description": "a GET request for a outage report on two entities", + "description": "a time limited GET request for a scheduled_maintenance report on two entities", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/outage_report/entities/1234,5678" + "path": "/scheduled_maintenance_report/entities/1234,5678", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { "status": 200, @@ -579,9 +575,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ + "scheduled_maintenance_reports": [ { - "outages": [ + "scheduled_maintenances": [ ], "links": { @@ -594,7 +590,7 @@ } }, { - "outages": [ + "scheduled_maintenances": [ ], "links": { @@ -611,12 +607,11 @@ } }, { - "description": "a time limited GET request for a outage report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a downtime report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/outage_report/entities/1234", - "query": "start_time=2014-09-26T14%3A45%3A21%2B09%3A30&end_time=2014-09-27T02%3A45%3A21%2B09%3A30" + "path": "/downtime_report/entities/1234,5678" }, "response": { "status": 200, @@ -624,30 +619,21 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ + "downtime_reports": [ + { + }, { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } } ] } } }, { - "description": "a GET request for a unscheduled_maintenance report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a unscheduled_maintenance report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/entities/1234,5678" + "path": "/unscheduled_maintenance_report/checks" }, "response": { "status": 200, @@ -668,19 +654,6 @@ "www.example.com:SSH" ] } - }, - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } } ] } @@ -692,7 +665,7 @@ "request": { "method": "get", "path": "/outage_report/checks/www.example.com:SSH", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { "status": 200, @@ -719,11 +692,11 @@ } }, { - "description": "a GET request for a status report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a scheduled_maintenance report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/status_report/entities/1234,5678" + "path": "/scheduled_maintenance_report/entities" }, "response": { "status": 200, @@ -731,22 +704,30 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "status_reports": [ - { - }, + "scheduled_maintenance_reports": [ { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } } }, { - "description": "a time limited GET request for a scheduled_maintenance report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a unscheduled_maintenance report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/scheduled_maintenance_report/entities/1234,5678", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -754,9 +735,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "unscheduled_maintenance_reports": [ { - "scheduled_maintenances": [ + "unscheduled_maintenances": [ ], "links": { @@ -767,30 +748,18 @@ "www.example.com:SSH" ] } - }, - { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } } ] } } }, { - "description": "a GET request for a downtime report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a time limited GET request for a downtime report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/downtime_report/entities" + "path": "/downtime_report/entities/1234,5678", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { "status": 200, @@ -799,6 +768,8 @@ }, "body": { "downtime_reports": [ + { + }, { } ] @@ -806,11 +777,11 @@ } }, { - "description": "a GET request for a unscheduled_maintenance report on one entity", + "description": "a GET request for a scheduled_maintenance report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/entities/1234" + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -818,9 +789,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenance_reports": [ + "scheduled_maintenance_reports": [ { - "unscheduled_maintenances": [ + "scheduled_maintenances": [ ], "links": { @@ -837,11 +808,12 @@ } }, { - "description": "a GET request for a outage report on all entities", + "description": "a time limited GET request for a downtime report on one entity", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/outage_report/entities" + "path": "/downtime_report/entities/1234", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { "status": 200, @@ -849,30 +821,19 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ + "downtime_reports": [ { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } } ] } } }, { - "description": "a GET request for a downtime report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a status report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/downtime_report/checks/www.example.com:SSH,www2.example.com:PING" + "path": "/status_report/entities" }, "response": { "status": 200, @@ -880,9 +841,7 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ - { - }, + "status_reports": [ { } ] @@ -921,11 +880,11 @@ } }, { - "description": "a GET request for a outage report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a outage report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/outage_report/checks" + "path": "/outage_report/checks/www.example.com:SSH,www2.example.com:PING" }, "response": { "status": 200, @@ -946,17 +905,31 @@ "www.example.com:SSH" ] } + }, + { + "outages": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } } }, { - "description": "a GET request for a unscheduled_maintenance report on a single check", + "description": "a time limited GET request for a unscheduled_maintenance report on all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH" + "path": "/unscheduled_maintenance_report/checks", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { "status": 200, @@ -983,12 +956,34 @@ } }, { - "description": "a time limited GET request for a outage report on two entities", + "description": "a GET request for a status report on two entities", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/outage_report/entities/1234,5678", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "path": "/status_report/entities/1234,5678" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "status_reports": [ + { + }, + { + } + ] + } + } + }, + { + "description": "a time-limited GET request for a outage report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "get", + "path": "/outage_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { "status": 200, @@ -1028,12 +1023,12 @@ } }, { - "description": "a time-limited GET request for a scheduled_maintenance report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a time limited GET request for a scheduled_maintenance report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/scheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "path": "/scheduled_maintenance_report/entities", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { "status": 200, @@ -1054,27 +1049,58 @@ "www.example.com:SSH" ] } - }, - { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } } ] } } }, { - "description": "a GET request for a downtime report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a unscheduled_maintenance report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "get", + "path": "/unscheduled_maintenance_report/entities/1234,5678" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "unscheduled_maintenance_reports": [ + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } + } + ] + } + } + }, + { + "description": "a GET request for a downtime report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", "path": "/downtime_report/entities/1234" @@ -1093,11 +1119,11 @@ } }, { - "description": "a GET request for a scheduled_maintenance report on a single check", + "description": "a GET request for a unscheduled_maintenance report on all entities", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/scheduled_maintenance_report/checks/www.example.com:SSH" + "path": "/unscheduled_maintenance_report/entities" }, "response": { "status": 200, @@ -1105,9 +1131,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "unscheduled_maintenance_reports": [ { - "scheduled_maintenances": [ + "unscheduled_maintenances": [ ], "links": { @@ -1124,12 +1150,12 @@ } }, { - "description": "a time limited GET request for a scheduled_maintenance report on all checks", + "description": "a time limited GET request for a outage report on all entities", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/scheduled_maintenance_report/checks", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "path": "/outage_report/entities", + "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { "status": 200, @@ -1137,9 +1163,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "outage_reports": [ { - "scheduled_maintenances": [ + "outages": [ ], "links": { @@ -1156,11 +1182,11 @@ } }, { - "description": "a GET request for a status report on all checks", + "description": "a GET request for a outage report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/status_report/checks" + "path": "/outage_report/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -1168,20 +1194,30 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "status_reports": [ + "outage_reports": [ { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } } }, { - "description": "a time limited GET request for a outage report on all checks", + "description": "a GET request for a status report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/outage_report/checks", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "path": "/status_report/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -1189,9 +1225,29 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ + "status_reports": [ { - "outages": [ + } + ] + } + } + }, + { + "description": "a GET request for a unscheduled_maintenance report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "get", + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "unscheduled_maintenance_reports": [ + { + "unscheduled_maintenances": [ ], "links": { @@ -1202,17 +1258,31 @@ "www.example.com:SSH" ] } + }, + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } } }, { - "description": "a GET request for a status report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a time limited GET request for a scheduled_maintenance report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/status_report/checks/www.example.com:SSH,www2.example.com:PING" + "path": "/scheduled_maintenance_report/entities/1234", + "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30&end_time=2014-10-03T09%3A10%3A17%2B09%3A30" }, "response": { "status": 200, @@ -1220,21 +1290,30 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "status_reports": [ - { - }, + "scheduled_maintenance_reports": [ { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } } }, { - "description": "a GET request for a downtime report on all checks", + "description": "a GET request for a outage report on all entities", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/downtime_report/checks" + "path": "/outage_report/entities" }, "response": { "status": 200, @@ -1242,19 +1321,30 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ + "outage_reports": [ { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } } }, { - "description": "a GET request for a outage report on two checks", + "description": "a GET request for a outage report on two entities", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/outage_report/checks/www.example.com:SSH,www2.example.com:PING" + "path": "/outage_report/entities/1234,5678" }, "response": { "status": 200, @@ -1294,12 +1384,33 @@ } }, { - "description": "a time-limited GET request for a outage report on two checks", + "description": "a time limited GET request for a downtime report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/downtime_report/checks/www.example.com:SSH", + "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30&end_time=2014-10-03T09%3A10%3A17%2B09%3A30" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "downtime_reports": [ + { + } + ] + } + } + }, + { + "description": "a time-limited GET request for a downtime report on two checks", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/outage_report/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "path": "/downtime_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30&end_time=2014-10-03T09%3A10%3A17%2B09%3A30" }, "response": { "status": 200, @@ -1307,9 +1418,32 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ + "downtime_reports": [ { - "outages": [ + }, + { + } + ] + } + } + }, + { + "description": "a time-limited GET request for a scheduled_maintenance report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "get", + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30&end_time=2014-10-03T09%3A10%3A17%2B09%3A30" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ ], "links": { @@ -1322,7 +1456,7 @@ } }, { - "outages": [ + "scheduled_maintenances": [ ], "links": { @@ -1339,11 +1473,12 @@ } }, { - "description": "a GET request for a scheduled_maintenance report on two entities", + "description": "a time limited GET request for a outage report on two entities", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/scheduled_maintenance_report/entities/1234,5678" + "path": "/outage_report/entities/1234,5678", + "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30&end_time=2014-10-03T09%3A10%3A17%2B09%3A30" }, "response": { "status": 200, @@ -1351,9 +1486,9 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "outage_reports": [ { - "scheduled_maintenances": [ + "outages": [ ], "links": { @@ -1366,7 +1501,7 @@ } }, { - "scheduled_maintenances": [ + "outages": [ ], "links": { @@ -1383,12 +1518,11 @@ } }, { - "description": "a time limited GET request for a downtime report on one entity", + "description": "a GET request for a status report on one entity", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/downtime_report/entities/1234", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "path": "/status_report/entities/1234" }, "response": { "status": 200, @@ -1396,7 +1530,7 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ + "status_reports": [ { } ] @@ -1404,12 +1538,12 @@ } }, { - "description": "a time limited GET request for a unscheduled_maintenance report on all checks", + "description": "a time limited GET request for a unscheduled_maintenance report on all entities", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/checks", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "path": "/unscheduled_maintenance_report/entities", + "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30&end_time=2014-10-03T09%3A10%3A17%2B09%3A30" }, "response": { "status": 200, @@ -1435,34 +1569,13 @@ } } }, - { - "description": "a time limited GET request for a downtime report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "get", - "path": "/downtime_report/checks", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "downtime_reports": [ - { - } - ] - } - } - }, { "description": "a time limited GET request for a unscheduled_maintenance report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30&end_time=2014-10-03T09%3A10%3A17%2B09%3A30" }, "response": { "status": 200, @@ -1489,12 +1602,11 @@ } }, { - "description": "a time limited GET request for a scheduled_maintenance report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a downtime report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/scheduled_maintenance_report/entities/1234", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "path": "/downtime_report/checks/www.example.com:SSH,www2.example.com:PING" }, "response": { "status": 200, @@ -1502,30 +1614,21 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "downtime_reports": [ + { + }, { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } } ] } } }, { - "description": "a GET request for a outage report on one entity", + "description": "a GET request for a outage report on all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/outage_report/entities/1234" + "path": "/outage_report/checks" }, "response": { "status": 200, @@ -1552,12 +1655,11 @@ } }, { - "description": "a time limited GET request for a unscheduled_maintenance report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a downtime report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/entities/1234,5678", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "path": "/downtime_report/entities" }, "response": { "status": 200, @@ -1565,44 +1667,19 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - }, + "downtime_reports": [ { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } } ] } } }, { - "description": "a time limited GET request for a downtime report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for one set of pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { "method": "get", - "path": "/downtime_report/entities", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "path": "/pagerduty_credentials/abc" }, "response": { "status": 200, @@ -1610,52 +1687,42 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ + "pagerduty_credentials": [ { + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } } }, { - "description": "a time limited GET request for a unscheduled_maintenance report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for one set of pagerduty credentials", + "provider_state": "no contact exists", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/entities/1234", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "path": "/pagerduty_credentials/abc" }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } + "errors": [ + "could not find contact 'abc'" ] } } }, { - "description": "a time-limited GET request for a downtime report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for all pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { "method": "get", - "path": "/downtime_report/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "path": "/pagerduty_credentials" }, "response": { "status": 200, @@ -1663,21 +1730,23 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ - { - }, + "pagerduty_credentials": [ { + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } } }, { - "description": "a GET request for a status report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for two sets of pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", "request": { "method": "get", - "path": "/status_report/entities/1234" + "path": "/pagerduty_credentials/abc,872" }, "response": { "status": 200, @@ -1685,486 +1754,542 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "status_reports": [ + "pagerduty_credentials": [ + { + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" + }, { + "service_key": "mno", + "subdomain": "pqr", + "username": "stu", + "password": "vwx" } ] } } }, { - "description": "a GET request for a unscheduled_maintenance report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for one set of pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/entities" + "method": "delete", + "path": "/pagerduty_credentials/abc", + "body": null }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a time limited GET request for a downtime report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a DELETE request for two sets of pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", "request": { - "method": "get", - "path": "/downtime_report/entities/1234,5678", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "method": "delete", + "path": "/pagerduty_credentials/abc,872", + "body": null }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "downtime_reports": [ - { - }, - { - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a time limited GET request for a unscheduled_maintenance report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for one set of pagerduty credentials", + "provider_state": "no contact exists", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/entities", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "method": "delete", + "path": "/pagerduty_credentials/abc", + "body": null }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } + "errors": [ + "could not find contact 'abc'" ] } } }, { - "description": "a GET request for a downtime report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a POST request with one set of pagerduty credentials", + "provider_state": "no contact exists", "request": { - "method": "get", - "path": "/downtime_report/entities/1234,5678" - }, - "response": { - "status": 200, + "method": "post", + "path": "/contacts/abc/pagerduty_credentials", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "downtime_reports": [ - { - }, + "pagerduty_credentials": [ { + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } - } - }, - { - "description": "a GET request for a scheduled_maintenance report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "get", - "path": "/scheduled_maintenance_report/entities" }, "response": { - "status": 200, + "status": 422, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ - { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } + "errors": [ + "Contact id: 'abc' could not be loaded" ] } } }, { - "description": "a GET request for a scheduled_maintenance report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one set of pagerduty credentials", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "get", - "path": "/scheduled_maintenance_report/entities/1234" - }, - "response": { - "status": 200, + "method": "post", + "path": "/contacts/abc/pagerduty_credentials", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenance_reports": [ + "pagerduty_credentials": [ { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc" + ] } }, { - "description": "a time limited GET request for a outage report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request for pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { - "method": "get", - "path": "/outage_report/entities", - "query": "start_time=2014-09-26T14%3A45%3A22%2B09%3A30&end_time=2014-09-27T02%3A45%3A22%2B09%3A30" + "method": "patch", + "path": "/pagerduty_credentials/abc", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" + } + ] }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", + "request": { + "method": "patch", + "path": "/pagerduty_credentials/abc,872", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for pagerduty credentials", + "provider_state": "no contact exists", + "request": { + "method": "patch", + "path": "/pagerduty_credentials/abc", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" + } + ] + }, + "response": { + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ - { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } + "errors": [ + "could not find contact 'abc'" ] } } }, { - "description": "a time limited GET request for a scheduled_maintenance report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "get", - "path": "/scheduled_maintenance_report/entities", - "query": "start_time=2014-09-26T14%3A45%3A23%2B09%3A30&end_time=2014-09-27T02%3A45%3A23%2B09%3A30" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenance_reports": [ + "unscheduled_maintenances": [ { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a status report on a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "no check exists", "request": { - "method": "get", - "path": "/status_report/checks/www.example.com:SSH" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "status_reports": [ + "unscheduled_maintenances": [ { + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { - "description": "a time-limited GET request for a unscheduled_maintenance report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-09-26T14%3A45%3A23%2B09%3A30&end_time=2014-09-27T02%3A45%3A23%2B09%3A30" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - }, + "unscheduled_maintenances": [ { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a unscheduled_maintenance report on two checks", + "description": "a POST request with two unscheduled maintenance periods", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenance_reports": [ + "unscheduled_maintenances": [ { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "duration": 3600, + "summary": "working" }, { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a outage report on a single check", + "description": "a POST request with two unscheduled maintenance periods", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/outage_report/checks/www.example.com:SSH" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "outage_reports": [ + "unscheduled_maintenances": [ { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a downtime report on a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "get", - "path": "/downtime_report/checks/www.example.com:SSH" + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-10-02T21:10:17+09:30", + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "no check exists", + "request": { + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "downtime_reports": [ + "scheduled_maintenances": [ { + "start_time": "2014-10-02T21:10:17+09:30", + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { - "description": "a GET request for a unscheduled_maintenance report on all checks", + "description": "a POST request with one scheduled maintenance period", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/checks" + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-10-02T21:10:17+09:30", + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenance_reports": [ + "scheduled_maintenances": [ { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "start_time": "2014-10-02T21:10:17+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-10-02T23:10:17+09:30", + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a status report on all entities", + "description": "a POST request with two scheduled maintenance periods", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/status_report/entities" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "status_reports": [ + "scheduled_maintenances": [ + { + "start_time": "2014-10-02T21:10:17+09:30", + "duration": 3600, + "summary": "working" + }, { + "start_time": "2014-10-02T23:10:17+09:30", + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a time limited GET request for a downtime report on a single check", + "description": "a PATCH request for an unscheduled maintenance period", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/downtime_report/checks/www.example.com:SSH", - "query": "start_time=2014-09-26T14%3A45%3A23%2B09%3A30&end_time=2014-09-27T02%3A45%3A23%2B09%3A30" + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-10-02T21:10:17+09:30" + } + ] }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-10-02T21:10:17+09:30" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no check exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-10-02T21:10:17+09:30" + } + ] + }, + "response": { + "status": 404, "body": { - "downtime_reports": [ - { - } + "errors": [ + "could not find entity 'www.example.com'" ] } } }, { - "description": "a DELETE request for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "delete", - "path": "/contacts/abc", - "body": null + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30" }, "response": { "status": 204, @@ -2172,12 +2297,12 @@ } }, { - "description": "a DELETE request for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "delete", - "path": "/contacts/abc,872", - "body": null + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30" }, "response": { "status": 204, @@ -2185,249 +2310,297 @@ } }, { - "description": "a DELETE request for a single contact", - "provider_state": "no contact exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no check exists", "request": { "method": "delete", - "path": "/contacts/abc", - "body": null + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30" }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find contacts 'abc'" + "could not find entity 'www.example.com'" ] } } }, { - "description": "a POST request with one contact", - "provider_state": "no contact exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/contacts", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "unscheduled_maintenances": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 201, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "no entity exists", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, - "body": [ - "abc" - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + } + ] + } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } } }, { - "description": "a POST request with two contacts", - "provider_state": "no contact exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/contacts", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ - { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] - }, + "unscheduled_maintenances": [ { - "id": "def", - "first_name": "Joan", - "last_name": "Smith", - "email": "joans@example.com" + "duration": 3600, + "summary": "working" } ] } }, "response": { - "status": 201, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, - "body": [ - "abc", - "def" - ] + "body": { + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" + } + ] + } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a POST request with one contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/contacts", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "unscheduled_maintenances": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" } ] } }, "response": { - "status": 409, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "Contacts already exist with the following IDs: abc" + "scheduled_maintenances": [ + { + "start_time": "2014-10-02T21:10:18+09:30", + "duration": 3600, + "summary": "working" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a single contact", - "provider_state": "no contact exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "no entity exists", "request": { - "method": "get", - "path": "/contacts/abc" + "method": "post", + "path": "/scheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "scheduled_maintenances": [ + { + "start_time": "2014-10-02T21:10:18+09:30", + "duration": 3600, + "summary": "working" + } + ] + } }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ - "could not find contacts 'abc'" + "could not find entity '1234'" ] } } }, { - "description": "a GET request for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/contacts/abc" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "scheduled_maintenances": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "start_time": "2014-10-02T21:10:18+09:30", + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for all contacts", - "provider_state": "no contact exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/contacts" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ - + "scheduled_maintenances": [ + { + "start_time": "2014-10-02T21:10:18+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-10-02T23:10:18+09:30", + "duration": 3600, + "summary": "more work" + } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for all contacts", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/contacts" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "contacts": [ + "scheduled_maintenances": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC", - "tags": [ - "admin", - "night_shift" - ] + "start_time": "2014-10-02T21:10:18+09:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-10-02T23:10:18+09:30", + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a PATCH requestto change a link for a single contact", - "provider_state": "a contact with id '872' exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "patch", - "path": "/contacts/872", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-10-02T21:10:18+09:30" } ] }, @@ -2437,72 +2610,60 @@ } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "no contact exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "patch", - "path": "/contacts/323", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-10-02T21:10:18+09:30" } ] }, "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find contacts '323'" - ] - } + "status": 204, + "body": "" } }, { - "description": "a PATCH request to change properties for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no entity exists", "request": { "method": "patch", - "path": "/contacts/abc,872", + "path": "/unscheduled_maintenances/entities/1234", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-10-02T21:10:18+09:30" } ] }, "response": { - "status": 204, - "body": "" + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } } }, { - "description": "a PATCH request to change links for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "patch", - "path": "/contacts/abc,872", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" - } - ] + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-10-02T21%3A10%3A18%2B09%3A30" }, "response": { "status": 204, @@ -2510,21 +2671,12 @@ } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "patch", - "path": "/contacts/abc", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] + "method": "delete", + "path": "/scheduled_maintenances/entities/1234,5678", + "query": "start_time=2014-10-02T21%3A10%3A18%2B09%3A30" }, "response": { "status": 204, @@ -2532,103 +2684,157 @@ } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no entity exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-10-02T21%3A10%3A18%2B09%3A30" + }, + "response": { + "status": 404, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, - { - "duration": 3600, - "summary": "more work" - } + "errors": [ + "could not find entity '1234'" ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "no check exists", + "description": "a GET request for sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/media/abc_sms" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "media": [ { - "duration": 3600, - "summary": "working" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } } ] } + } + }, + { + "description": "a GET request for sms media", + "provider_state": "no contact exists", + "request": { + "method": "get", + "path": "/media/abc_sms" }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find contact 'abc'" ] } } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for all media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "method": "get", + "path": "/media" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "media": [ { - "duration": 3600, - "summary": "working" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3, + "links": { + "contacts": [ + "abc" + ] + } + }, + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "method": "get", + "path": "/media/abc_email,abc_sms" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "media": [ { - "duration": 3600, - "summary": "working" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3, + "links": { + "contacts": [ + "abc" + ] + } }, { - "duration": 3600, - "summary": "more work" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } } ] } + } + }, + { + "description": "a DELETE request for one medium", + "provider_state": "a contact with id 'abc' has email and sms media", + "request": { + "method": "delete", + "path": "/media/abc_email", + "body": null }, "response": { "status": 204, @@ -2636,22 +2842,12 @@ } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for two media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } - ] - } + "method": "delete", + "path": "/media/abc_email,abc_sms", + "body": null }, "response": { "status": 204, @@ -2659,153 +2855,143 @@ } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for one medium", + "provider_state": "no contact exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-26T14:45:23+09:30", - "duration": 3600, - "summary": "working" - }, - { - "start_time": "2014-09-26T16:45:23+09:30", - "duration": 3600, - "summary": "more work" - } - ] - } + "method": "delete", + "path": "/media/abc_email", + "body": null }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "no check exists", - "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "status": 404, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-26T14:45:23+09:30", - "duration": 3600, - "summary": "working" - } - ] - } - }, - "response": { - "status": 404, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find contact 'abc'" ] } } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a POST request with one medium", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "path": "/contacts/abc/media", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "media": [ { - "start_time": "2014-09-26T14:45:23+09:30", - "duration": 3600, - "summary": "working" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc_sms" + ] } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a POST request with two media", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "path": "/contacts/abc/media", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "media": [ { - "start_time": "2014-09-26T14:45:23+09:30", - "duration": 3600, - "summary": "working" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 }, { - "start_time": "2014-09-26T16:45:23+09:30", - "duration": 3600, - "summary": "more work" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3 } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc_sms", + "abc_email" + ] } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one medium", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "path": "/contacts/abc/media", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "media": [ { - "start_time": "2014-09-26T14:45:23+09:30", - "duration": 3600, - "summary": "working" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 } ] } }, "response": { - "status": 204, - "body": "" + "status": 422, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "Contact id: 'abc' could not be loaded" + ] + } } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request for email media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/media/abc_email", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T14:45:23+09:30" + "path": "/media/0/interval", + "value": 50 + }, + { + "op": "replace", + "path": "/media/0/rollup_threshold", + "value": 3 } ] }, @@ -2815,19 +3001,24 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a PATCH request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "path": "/media/abc_email,abc_sms", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T14:45:23+09:30" + "path": "/media/0/interval", + "value": 50 + }, + { + "op": "replace", + "path": "/media/0/rollup_threshold", + "value": 3 } ] }, @@ -2837,95 +3028,129 @@ } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no check exists", + "description": "a PATCH request for email media", + "provider_state": "no contact exists", "request": { "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "path": "/media/abc_email", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T14:45:23+09:30" + "path": "/media/0/interval", + "value": 50 } ] }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find contact 'abc'" ] } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for a single contact", + "provider_state": "no contact exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-26T14%3A45%3A23%2B09%3A30" + "method": "get", + "path": "/contacts/abc" }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts 'abc'" + ] + } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a single contact", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-09-26T14%3A45%3A23%2B09%3A30" + "method": "get", + "path": "/contacts/abc" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC" + } + ] + } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no check exists", + "description": "a GET request for all contacts", + "provider_state": "no contact exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-09-26T14%3A45%3A23%2B09%3A30" + "method": "get", + "path": "/contacts" }, "response": { - "status": 404, + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { - "errors": [ - "could not find entity 'www.example.com'" + "contacts": [ + ] } } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for all contacts", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "method": "get", + "path": "/contacts" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, + "contacts": [ { - "duration": 3600, - "summary": "more work" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC" } ] } + } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null }, "response": { "status": 204, @@ -2933,49 +3158,12 @@ } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "no entity exists", - "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } - ] - } - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } - } - }, - { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a DELETE request for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } - ] - } + "method": "delete", + "path": "/contacts/abc,872", + "body": null }, "response": { "status": 204, @@ -2983,709 +3171,192 @@ } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a DELETE request for a single contact", + "provider_state": "no contact exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, - { - "duration": 3600, - "summary": "more work" - } - ] - } + "method": "delete", + "path": "/contacts/abc", + "body": null }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", - "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "status": 404, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } + "errors": [ + "could not find contacts 'abc'" ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with one contact", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "path": "/contacts", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-26T14:45:24+09:30", - "duration": 3600, - "summary": "working" - }, + "contacts": [ { - "start_time": "2014-09-26T16:45:24+09:30", - "duration": 3600, - "summary": "more work" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC" } ] } }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "no entity exists", - "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "status": 201, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-26T14:45:24+09:30", - "duration": 3600, - "summary": "working" - } - ] - } - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } + "body": [ + "abc" + ] } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a POST request with two contacts", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "path": "/contacts", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ + "contacts": [ { - "start_time": "2014-09-26T14:45:24+09:30", - "duration": 3600, - "summary": "working" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC" + }, + { + "id": "def", + "first_name": "Joan", + "last_name": "Smith", + "email": "joans@example.com" } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc", + "def" + ] } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a POST request with one contact", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "path": "/contacts", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-26T14:45:24+09:30", - "duration": 3600, - "summary": "working" - }, + "contacts": [ { - "start_time": "2014-09-26T16:45:24+09:30", - "duration": 3600, - "summary": "more work" + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC" } ] } }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", - "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "status": 409, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-09-26T14:45:24+09:30", - "duration": 3600, - "summary": "working" - } + "errors": [ + "Contacts already exist with the following IDs: abc" ] } - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", - "request": { - "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T14:45:24+09:30" - } - ] - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a PATCH request to change properties for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { "method": "patch", - "path": "/unscheduled_maintenances/entities/1234,5678", + "path": "/contacts/abc,872", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T14:45:24+09:30" + "path": "/contacts/0/timezone", + "value": "UTC" } ] }, "response": { "status": 204, "body": "" - } - }, - { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no entity exists", - "request": { - "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-09-26T14:45:24+09:30" - } - ] - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } - } - }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-26T14%3A45%3A24%2B09%3A30" - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234,5678", - "query": "start_time=2014-09-26T14%3A45%3A24%2B09%3A30" - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no entity exists", - "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-09-26T14%3A45%3A24%2B09%3A30" - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } - } - }, - { - "description": "a DELETE request for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", - "request": { - "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", - "request": { - "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a single notification rule", - "provider_state": "no notification rule exists", - "request": { - "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "body": null - }, - "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" - ] - } - } - }, - { - "description": "a POST request with one notification rule", - "provider_state": "a contact with id 'abc' exists", - "request": { - "method": "post", - "path": "/contacts/abc/notification_rules", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "notification_rules": [ - { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - } - ] - } - }, - "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - { - "json_class": "Pact::Term", - "data": { - "generate": "05983623-fcef-42da-af44-ed6990b500fa", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - } - ] - } - }, - { - "description": "a POST request with two notification rules", - "provider_state": "a contact with id 'abc' exists", - "request": { - "method": "post", - "path": "/contacts/abc/notification_rules", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "notification_rules": [ - { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - }, - { - "entity_tags": null, - "entities": [ - "foo-app-02.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": true, - "critical_blackhole": false - } - ] - } - }, - "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - { - "json_class": "Pact::Term", - "data": { - "generate": "05983623-fcef-42da-af44-ed6990b500fa", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - }, - { - "json_class": "Pact::Term", - "data": { - "generate": "20f182fc-6e32-4794-9007-97366d162c51", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - } - ] - } - }, - { - "description": "a POST request with one notification rule", - "provider_state": "no contact exists", - "request": { - "method": "post", - "path": "/contacts/abc/notification_rules", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "notification_rules": [ - { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - } - ] - } - }, - "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find contact 'abc'" - ] - } - } - }, - { - "description": "a GET request for a single notification rule", - "provider_state": "no notification rule exists", - "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" - }, - "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find notification rules '05983623-fcef-42da-af44-ed6990b500fa'" - ] - } - } - }, - { - "description": "a GET request for all notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", - "request": { - "method": "get", - "path": "/notification_rules" - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "notification_rules": [ - { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - } - ] - } - } - }, - { - "description": "a GET request for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", - "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "notification_rules": [ - { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - } - ] - } - } - }, - { - "description": "a GET request for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", - "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51" - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "notification_rules": [ - { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - }, - { - "id": "20f182fc-6e32-4794-9007-97366d162c51", - "tags": [ - "physical" - ], - "regex_tags": [ - - ], - "entities": [ - "example.com" - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": true, - "critical_blackhole": true - } + } + }, + { + "description": "a PATCH request to change properties for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "patch", + "path": "/contacts/323", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contacts '323'" ] } } }, { - "description": "a PATCH request to change properties for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "description": "a PATCH request to change properties for a single contact", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "path": "/contacts/abc", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false + "path": "/contacts/0/timezone", + "value": "UTC" } ] }, @@ -3695,19 +3366,19 @@ } }, { - "description": "a PATCH request to change properties for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", + "description": "a PATCH request to change links for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", + "path": "/contacts/abc,872", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { - "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" } ] }, @@ -3717,32 +3388,25 @@ } }, { - "description": "a PATCH request to change properties for a single notification rule", - "provider_state": "no notification rule exists", + "description": "a PATCH requestto change a link for a single contact", + "provider_state": "a contact with id '872' exists", "request": { "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "path": "/contacts/872", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { - "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" } ] }, "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" - ] - } + "status": 204, + "body": "" } }, { @@ -3867,49 +3531,239 @@ } }, { - "description": "a GET request for all entities", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for all entities", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "get", + "path": "/entities" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "entities": [ + { + "name": "www.example.com", + "id": "1234" + } + ] + } + } + }, + { + "description": "a PATCH request for a single entity", + "provider_state": "no entity exists", + "request": { + "method": "patch", + "path": "/entities/1234", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/entities/0/name", + "value": "example3.com" + } + ] + }, + "response": { + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } + } + }, + { + "description": "a PATCH request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", + "request": { + "method": "patch", + "path": "/entities/1234", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/entities/0/name", + "value": "example3.com" + } + ] + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one test notification", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH,www2.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one test notification", + "provider_state": "no check exists", + "request": { + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + } + ] + } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } + } + }, + { + "description": "a POST request with one test notification", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two test notifications", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH,www2.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + }, + { + "summary": "more tests" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with two test notifications", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + }, + { + "summary": "more tests" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one test notification", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/entities" - }, - "response": { - "status": 200, + "method": "post", + "path": "/test_notifications/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "test_notifications": [ { - "name": "www.example.com", - "id": "1234" + "summary": "testing" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a PATCH request for a single entity", + "description": "a POST request with one test notification", "provider_state": "no entity exists", "request": { - "method": "patch", - "path": "/entities/1234", + "method": "post", + "path": "/test_notifications/entities/1234", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" - } - ] + "body": { + "test_notifications": [ + { + "summary": "testing" + } + ] + } }, "response": { "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, "body": { "errors": [ "could not find entity '1234'" @@ -3918,21 +3772,21 @@ } }, { - "description": "a PATCH request for a single entity", + "description": "a POST request with one test notification", "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "patch", - "path": "/entities/1234", + "method": "post", + "path": "/test_notifications/entities/1234", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" - } - ] + "body": { + "test_notifications": [ + { + "summary": "testing" + } + ] + } }, "response": { "status": 204, @@ -3941,10 +3795,10 @@ }, { "description": "a POST request with two test notifications", - "provider_state": "a check 'www.example.com:SSH' exists", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", + "path": "/test_notifications/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, @@ -3965,11 +3819,11 @@ } }, { - "description": "a POST request with one test notification", - "provider_state": "no check exists", + "description": "a POST request with two test notifications", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", + "path": "/test_notifications/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, @@ -3977,82 +3831,206 @@ "test_notifications": [ { "summary": "testing" + }, + { + "summary": "more tests" + } + ] + } + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a GET request for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "request": { + "method": "get", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "notification_rules": [ + { + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } + } + }, + { + "description": "a GET request for a single notification rule", + "provider_state": "no notification rule exists", + "request": { + "method": "get", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find notification rules '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a POST request with one test notification", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for all notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH,www2.example.com:PING", + "method": "get", + "path": "/notification_rules" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ + "notification_rules": [ { - "summary": "testing" + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two test notifications", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH,www2.example.com:PING", + "method": "get", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ + "notification_rules": [ { - "summary": "testing" + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false }, { - "summary": "more tests" + "id": "20f182fc-6e32-4794-9007-97366d162c51", + "tags": [ + "physical" + ], + "regex_tags": [ + + ], + "entities": [ + "example.com" + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": true, + "critical_blackhole": true } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one test notification", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "test_notifications": [ - { - "summary": "testing" - } - ] - } + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "body": null }, "response": { "status": 204, @@ -4060,24 +4038,12 @@ } }, { - "description": "a POST request with two test notifications", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a DELETE request for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { - "method": "post", - "path": "/test_notifications/entities/1234", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "test_notifications": [ - { - "summary": "testing" - }, - { - "summary": "more tests" - } - ] - } + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", + "body": null }, "response": { "status": 204, @@ -4085,107 +4051,207 @@ } }, { - "description": "a POST request with one test notification", - "provider_state": "no entity exists", + "description": "a DELETE request for a single notification rule", + "provider_state": "no notification rule exists", "request": { - "method": "post", - "path": "/test_notifications/entities/1234", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "test_notifications": [ - { - "summary": "testing" - } - ] - } + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "body": null }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity '1234'" + "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a POST request with one test notification", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a POST request with one notification rule", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/test_notifications/entities/1234,5678", + "path": "/contacts/abc/notification_rules", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "test_notifications": [ + "notification_rules": [ { - "summary": "testing" + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + { + "json_class": "Pact::Term", + "data": { + "generate": "05983623-fcef-42da-af44-ed6990b500fa", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + } + ] } }, { - "description": "a POST request with two test notifications", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a POST request with two notification rules", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/test_notifications/entities/1234,5678", + "path": "/contacts/abc/notification_rules", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "test_notifications": [ + "notification_rules": [ { - "summary": "testing" + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false }, { - "summary": "more tests" + "entity_tags": null, + "entities": [ + "foo-app-02.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": true, + "critical_blackhole": false } ] } }, "response": { - "status": 204, - "body": "" + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + { + "json_class": "Pact::Term", + "data": { + "generate": "05983623-fcef-42da-af44-ed6990b500fa", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + }, + { + "json_class": "Pact::Term", + "data": { + "generate": "20f182fc-6e32-4794-9007-97366d162c51", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + } + ] } }, { - "description": "a POST request with one test notification", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with one notification rule", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/test_notifications/entities/1234", + "path": "/contacts/abc/notification_rules", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "test_notifications": [ + "notification_rules": [ { - "summary": "testing" + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find contact 'abc'" + ] + } } }, { - "description": "a DELETE request for one medium", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a PATCH request to change properties for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "delete", - "path": "/media/abc_email", - "body": null + "method": "patch", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] }, "response": { "status": 204, @@ -4193,12 +4259,21 @@ } }, { - "description": "a DELETE request for two media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a PATCH request to change properties for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { - "method": "delete", - "path": "/media/abc_email,abc_sms", - "body": null + "method": "patch", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] }, "response": { "status": 204, @@ -4206,12 +4281,21 @@ } }, { - "description": "a DELETE request for one medium", - "provider_state": "no contact exists", + "description": "a PATCH request to change properties for a single notification rule", + "provider_state": "no notification rule exists", "request": { - "method": "delete", - "path": "/media/abc_email", - "body": null + "method": "patch", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] }, "response": { "status": 404, @@ -4220,27 +4304,29 @@ }, "body": { "errors": [ - "could not find contact 'abc'" + "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a POST request with one medium", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with two checks", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/contacts/abc/media", + "path": "/checks", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "media": [ + "checks": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 + "name": "SSH", + "entity_id": "1234" + }, + { + "name": "PING", + "entity_id": "5678" } ] } @@ -4251,32 +4337,25 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "abc_sms" + "www.example.com:SSH", + "www2.example.com:PING" ] } }, { - "description": "a POST request with two media", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with one check", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/contacts/abc/media", + "path": "/checks", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "media": [ - { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 - }, + "checks": [ { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3 + "name": "SSH", + "entity_id": "1234" } ] } @@ -4287,49 +4366,16 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "abc_sms", - "abc_email" + "www.example.com:SSH" ] } }, { - "description": "a POST request with one medium", - "provider_state": "no contact exists", - "request": { - "method": "post", - "path": "/contacts/abc/media", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "media": [ - { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 - } - ] - } - }, - "response": { - "status": 422, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "Contact id: 'abc' could not be loaded" - ] - } - } - }, - { - "description": "a GET request for sms media", - "provider_state": "no contact exists", + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "no entity exists", "request": { "method": "get", - "path": "/media/abc_sms" + "path": "/checks/www.example.com:SSH" }, "response": { "status": 404, @@ -4338,17 +4384,17 @@ }, "body": { "errors": [ - "could not find contact 'abc'" + "could not find entity checks: 'www.example.com:SSH'" ] } } }, { - "description": "a GET request for all media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a GET request for check 'www.example.com:SSH'", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/media" + "path": "/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -4356,26 +4402,14 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ - { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3, - "links": { - "contacts": [ - "abc" - ] - } - }, + "checks": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", "links": { - "contacts": [ - "abc" + "entities": [ + "1234" ] } } @@ -4384,11 +4418,11 @@ } }, { - "description": "a GET request for sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a GET request for all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/media/abc_sms" + "path": "/checks" }, "response": { "status": 200, @@ -4396,15 +4430,14 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ + "checks": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, + "id": "www.example.com:SSH", + "name": "SSH", + "entity_name": "www.example.com", "links": { - "contacts": [ - "abc" + "entities": [ + "1234" ] } } @@ -4413,11 +4446,11 @@ } }, { - "description": "a GET request for email and sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a GET request for all checks", + "provider_state": "no entity exists", "request": { "method": "get", - "path": "/media/abc_email,abc_sms" + "path": "/checks" }, "response": { "status": 200, @@ -4425,114 +4458,61 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ - { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3, - "links": { - "contacts": [ - "abc" - ] - } - }, - { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, - "links": { - "contacts": [ - "abc" - ] - } - } + "checks": [ + ] } } }, { - "description": "a PATCH request for email media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a PATCH request for a single check", + "provider_state": "no entity exists", "request": { "method": "patch", - "path": "/media/abc_email", + "path": "/checks/www.example.com:SSH", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/media/0/interval", - "value": 50 - }, - { - "op": "replace", - "path": "/media/0/rollup_threshold", - "value": 3 + "path": "/checks/0/enabled", + "value": false } ] }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for email and sms media", - "provider_state": "a contact with id 'abc' has email and sms media", - "request": { - "method": "patch", - "path": "/media/abc_email,abc_sms", + "status": 404, "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - { - "op": "replace", - "path": "/media/0/interval", - "value": 50 - }, - { - "op": "replace", - "path": "/media/0/rollup_threshold", - "value": 3 - } - ] - }, - "response": { - "status": 204, - "body": "" + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { - "description": "a PATCH request for email media", - "provider_state": "no contact exists", + "description": "a PATCH request for a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "patch", - "path": "/media/abc_email", + "path": "/checks/www.example.com:SSH", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/media/0/interval", - "value": 50 + "path": "/checks/0/enabled", + "value": false } ] }, "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find contact 'abc'" - ] - } + "status": 204, + "body": "" } } ], From b5f47700db58e6f2d0523bfe0bfeb4f3a251c7c2 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 3 Oct 2014 10:16:01 +0930 Subject: [PATCH 25/69] fix media creation/patching in edit_contacts JS --- .../gateways/jsonapi/medium_methods.rb | 6 +++-- .../web/public/js/backbone.jsonapi.js | 18 +++++++++++++-- .../gateways/web/public/js/flapjack.js | 2 +- .../gateways/web/public/js/modules/contact.js | 23 ++++++++----------- .../gateways/web/public/js/modules/medium.js | 1 + 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/lib/flapjack/gateways/jsonapi/medium_methods.rb b/lib/flapjack/gateways/jsonapi/medium_methods.rb index ab835012c..3d21bcb3a 100644 --- a/lib/flapjack/gateways/jsonapi/medium_methods.rb +++ b/lib/flapjack/gateways/jsonapi/medium_methods.rb @@ -65,8 +65,10 @@ def self.registered(app) halt err(422, "No valid media were submitted") end - unless media_data.all? {|m| m['id'].nil? } - halt err(422, "Media creation cannot include IDs") + media_id_re = /^#{params[:contact_id]}_(?:#{Flapjack::Data::Contact::ALL_MEDIA.join('|')}$)/ + + unless media_data.all? {|m| m['id'].nil? || media_id_re === m['id'] } + halt err(422, "Media creation cannot include non-conformant IDs") end semaphore = obtain_semaphore(SEMAPHORE_CONTACT_MASS_UPDATE) diff --git a/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js b/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js index e4d533bff..1ac062511 100644 --- a/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +++ b/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js @@ -46,9 +46,23 @@ toolbox.batchRequest = function(klass, ids, amount, success) { Backbone.JSONAPIModel = Backbone.Model.extend({ + initialize: function() { + var _persisted; + + this.isPersisted = function () { + if ( !_.isUndefined(_persisted) && !_.isNull(_persisted) ) { + return(_persisted); + } else { + return(!_.isNull(this.id)); + } + }; + this.setPersisted = function(pers) { + _persisted = pers; + }; + }, + isNew: function() { - return( !_.isUndefined(this.persisted) && !_.isUndefined(this.persisted) - && (this.persisted == false)); + return(!this.isPersisted()); }, // the following two methods, and batchRequest, should be folded into diff --git a/lib/flapjack/gateways/web/public/js/flapjack.js b/lib/flapjack/gateways/web/public/js/flapjack.js index 95cc9ac8f..8c42e3685 100644 --- a/lib/flapjack/gateways/web/public/js/flapjack.js +++ b/lib/flapjack/gateways/web/public/js/flapjack.js @@ -45,7 +45,7 @@ $(document).ready(function() { if ( $('#contactModal').hasClass('in') ) { return; } var contact = new (Contact.Model)(); - contact.persisted = false; + contact.setPersisted(false); contact.set('id', toolbox.generateUUID()); var contactDetailsView = new (Contact.Views.ContactDetails)({model: contact}); diff --git a/lib/flapjack/gateways/web/public/js/modules/contact.js b/lib/flapjack/gateways/web/public/js/modules/contact.js index 2b08f1d58..65db21654 100644 --- a/lib/flapjack/gateways/web/public/js/modules/contact.js +++ b/lib/flapjack/gateways/web/public/js/modules/contact.js @@ -17,6 +17,7 @@ links: {}, }, initialize: function(){ + Backbone.JSONAPIModel.prototype.initialize.apply(this, arguments); this.on('change', this.setDirty, this); }, toJSON: function() { @@ -65,17 +66,7 @@ this.collection.each(function(contact) { var item = new (Contact.Views.ListItem)({ model: contact }); - var itemEl = item.render().$el; - - itemEl.on('mouseenter', function(e) { - e.stopPropagation(); - $(this).find('td.actions button').css('visibility', 'visible'); - }).on('mouseleave', function(e) { - e.stopPropagation(); - $(this).find('td.actions button').css('visibility', 'hidden'); - }); - - jqel.append(itemEl); + jqel.append(item.render().$el); }); return this; @@ -122,7 +113,7 @@ var context = this; - var deferreds = this.model.resolveLinks({media: Medium.List}); + var deferreds = this.model.resolveLinks({media: Medium.List}); $.when.apply($, deferreds).done( function() { @@ -214,6 +205,7 @@ if ( this.model.isNew() ) { var save_success = function(model, response, options) { + model.setPersisted(true); flapjack.contactList.add(model); $('#contactModal').modal('hide'); }; @@ -297,8 +289,10 @@ type: type, address: '', interval: 15, - rollup_threshold: 3, + rollup_threshold: 3 }); + medium.setPersisted(false); + medium.set('id', options.contact.get('id') + '_' + type); context.collection.add(medium); } medium.contact = options.contact; @@ -365,7 +359,8 @@ var attrs = _.pick(model.attributes, changedAttrKeys); if ( model.isNew() ) { model.save(attrs); - model.set('id', model.contact.get('id') + '_' + model.get('type')); + model.setPersisted(true); + model.contact.addLinked('contacts', 'media', model); } else { model.patch('media', attrs); } diff --git a/lib/flapjack/gateways/web/public/js/modules/medium.js b/lib/flapjack/gateways/web/public/js/modules/medium.js index 89f14882f..55333c70a 100644 --- a/lib/flapjack/gateways/web/public/js/modules/medium.js +++ b/lib/flapjack/gateways/web/public/js/modules/medium.js @@ -6,6 +6,7 @@ Medium.Model = Backbone.JSONAPIModel.extend({ name: 'media', initialize: function(){ + Backbone.JSONAPIModel.prototype.initialize.apply(this, arguments); this.on('change', this.setDirty, this); }, defaults: { From 074677f224256d9d2a74d6633e047e720e267081 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 3 Oct 2014 13:00:12 +0930 Subject: [PATCH 26/69] hardcode hiredis driver for receivers --- lib/flapjack/cli/receiver.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index c5215900c..7fe276219 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -2,6 +2,7 @@ require 'dante' require 'redis' +require 'hiredis' require 'oj' Oj.default_options = { :indent => 0, :mode => :strict } @@ -117,7 +118,7 @@ def mirror private def redis - @redis ||= Redis.new(@redis_options) + @redis ||= Redis.new(@redis_options.merge(:driver => :hiredis)) end def runner(type) @@ -298,7 +299,6 @@ def array_append(array, value) end def json_feeder(opts = {}) - input = if opts[:from] File.open(opts[:from]) # Explodes if file does not exist. elsif $stdin.tty? @@ -335,7 +335,7 @@ def mirror_receive(opts) source_addr = opts[:source] - source_redis = Redis.new(:url => source_addr) + source_redis = Redis.new(:url => source_addr, :driver => :hiredis) refresh_archive_index(source_addr, :redis => source_redis) archives = mirror_get_archive_keys_stats(source_redis) From b5867f4e75f96ad5ea1b4e8fa78dd23c1d87fe2a Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 3 Oct 2014 13:14:17 +0930 Subject: [PATCH 27/69] llen instead of scard for archive length --- lib/flapjack/cli/receiver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index 7fe276219..28fec74fe 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -410,7 +410,7 @@ def refresh_archive_index(name, opts = {}) # refresh the key name cache, avoid repeated calls to redis KEYS # this cache will be updated any time a new archive bucket is created archive_keys = source_redis.keys("events_archive:*").group_by do |ak| - (source_redis.scard(ak) > 0) ? 't' : 'f' + (source_redis.llen(ak) > 0) ? 't' : 'f' end redis.srem("known_events_archive_keys:#{name}", archive_keys['f']) unless archive_keys['f'].empty? From 474e37c56dc8ea591e9f2e8da69224686231de5e Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 3 Oct 2014 14:17:24 +0930 Subject: [PATCH 28/69] more paranoid archive refreshing --- lib/flapjack/cli/receiver.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index 0cd2ad5e8..7c2127a1d 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -410,8 +410,10 @@ def refresh_archive_index(name, opts = {}) (source_redis.llen(ak) > 0) ? 't' : 'f' end - redis.srem("known_events_archive_keys:#{name}", archive_keys['f']) unless archive_keys['f'].empty? - redis.sadd("known_events_archive_keys:#{name}", archive_keys['t']) unless archive_keys['t'].empty? + {'f' => :srem, 't' => :sadd}.each_pair do |k, cmd| + next unless archive_keys.has_key?(k) && !archive_keys[k].empty? + redis.send(cmd, "known_events_archive_keys:#{name}", archive_keys[k]) + end end end From 9d563fcb9b38731b277b5b4e65a30f0ac7a14432 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 3 Oct 2014 14:26:22 +0930 Subject: [PATCH 29/69] when changing method args, change them *everywhere* --- lib/flapjack/cli/receiver.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index 7c2127a1d..50aa2e84a 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -335,7 +335,7 @@ def mirror_receive(opts) source_redis = Redis.new(:url => source_addr, :driver => :hiredis) refresh_archive_index(source_addr, :redis => source_redis) - archives = mirror_get_archive_keys_stats(source_redis) + archives = mirror_get_archive_keys_stats(source_addr, :redis => source_redis) raise "found no archives!" if archives.empty? puts "found archives: #{archives.inspect}" @@ -398,7 +398,7 @@ def mirror_receive(opts) def mirror_get_archive_keys_stats(name, opts = {}) source_redis = opts[:redis] redis.smembers("known_events_archive_keys:#{name}").sort.collect do |eak| - {:name => eak, :size => source_redis.llen(eak)} + {:name => eak, :size => source_redis.llen(eak)} end end From 7e2c3b67aa804bc1504b43ad72d894183b0321b4 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 3 Oct 2014 14:36:33 +0930 Subject: [PATCH 30/69] fix mirroring 'caught-up' state --- lib/flapjack/cli/receiver.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index 50aa2e84a..af650c9f4 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -389,9 +389,14 @@ def mirror_receive(opts) archive_idx = archives.index {|a| a[:name] == archive_key } archive_idx = archive_idx.nil? ? 0 : (archive_idx + 1) - archive_key = archives[archive_idx][:name] - puts archive_key - cursor = -1 + if archives[archive_idx] + archive_key = archives[archive_idx][:name] + puts archive_key + cursor = -1 + else + break unless opts[:follow] + sleep 1 + end end end From c0861a36c693fd99f158ee2d1ab67af82ac2ccd0 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 3 Oct 2014 15:44:45 +0930 Subject: [PATCH 31/69] hacky tag speedup; bring on flapjack v2 :P --- lib/flapjack/coordinator.rb | 6 ++++++ lib/flapjack/data/tagged.rb | 12 +----------- spec/lib/flapjack/coordinator_spec.rb | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/lib/flapjack/coordinator.rb b/lib/flapjack/coordinator.rb index fef14a85f..dca87f891 100644 --- a/lib/flapjack/coordinator.rb +++ b/lib/flapjack/coordinator.rb @@ -32,6 +32,12 @@ def start(options = {}) EM.synchrony do setup_signals if options[:signals] + redis = Flapjack::RedisPool.new(:config => @redis_options, :size => 1) + ['entity', 'check'].each do |type| + discovered = redis.keys("#{type}_tag:*") + redis.sadd("known_tags:#{type}_tag", discovered) unless discovered.empty? + end + begin add_pikelets(pikelets(@config.all)) loop do diff --git a/lib/flapjack/data/tagged.rb b/lib/flapjack/data/tagged.rb index b6e1b9623..ef23a586b 100644 --- a/lib/flapjack/data/tagged.rb +++ b/lib/flapjack/data/tagged.rb @@ -14,20 +14,10 @@ def known_key "known_tags:#{tag_prefix}" end - def known_tags - if @redis.scard(known_key) == 0 - discovered = @redis.keys("#{tag_prefix}:*") - @redis.sadd(known_key, discovered) unless discovered.empty? - discovered - else - @redis.smembers(known_key) - end - end - # return the set of tags for this object def tags return @tags unless @tags.nil? - @tags ||= Set.new( known_tags.inject([]) {|memo, t| + @tags ||= Set.new( @redis.smembers(known_key).inject([]) {|memo, t| tag_key = "#{tag_prefix}:#{t}" memo << t if @redis.sismember(tag_key, @id.to_s) memo diff --git a/spec/lib/flapjack/coordinator_spec.rb b/spec/lib/flapjack/coordinator_spec.rb index 64c91021f..543550558 100644 --- a/spec/lib/flapjack/coordinator_spec.rb +++ b/spec/lib/flapjack/coordinator_spec.rb @@ -9,6 +9,8 @@ let(:logger) { double(Flapjack::Logger) } + let(:redis) { double(::Redis) } + let!(:time) { Time.now } it "starts and stops a pikelet" do @@ -19,6 +21,10 @@ expect(config).to receive(:for_redis).and_return({}) expect(config).to receive(:all).twice.and_return(cfg) + expect(redis).to receive(:keys).with('entity_tag:*').and_return([]) + expect(redis).to receive(:keys).with('check_tag:*').and_return([]) + expect(Flapjack::RedisPool).to receive(:new).and_return(redis) + processor = double('processor') expect(processor).to receive(:start) expect(processor).to receive(:stop) @@ -52,6 +58,10 @@ expect(config).to receive(:for_redis).and_return({}) expect(config).to receive(:all).twice.and_return(cfg) + expect(redis).to receive(:keys).with('entity_tag:*').and_return([]) + expect(redis).to receive(:keys).with('check_tag:*').and_return([]) + expect(Flapjack::RedisPool).to receive(:new).and_return(redis) + processor = double('processor') expect(processor).to receive(:start).and_raise(RuntimeError) expect(processor).to receive(:stop) @@ -79,6 +89,10 @@ expect(config).to receive(:for_redis).and_return({}) expect(config).to receive(:all).twice.and_return(cfg) + expect(redis).to receive(:keys).with('entity_tag:*').and_return([]) + expect(redis).to receive(:keys).with('check_tag:*').and_return([]) + expect(Flapjack::RedisPool).to receive(:new).and_return(redis) + processor = double('processor') expect(processor).to receive(:start) expect(processor).to receive(:stop) @@ -121,6 +135,10 @@ expect(config).to receive(:for_redis).and_return({}) expect(config).to receive(:all).twice.and_return(cfg) + expect(redis).to receive(:keys).with('entity_tag:*').and_return([]) + expect(redis).to receive(:keys).with('check_tag:*').and_return([]) + expect(Flapjack::RedisPool).to receive(:new).and_return(redis) + processor = double('processor') expect(processor).to receive(:start) expect(processor).to receive(:stop) From 41df724b562f3dd7bfe6e6ed009d163a4c71798e Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Wed, 8 Oct 2014 10:31:12 +1030 Subject: [PATCH 32/69] add filter to event mirror --- features/cli_receive-events.feature | 2 +- lib/flapjack/cli/receiver.rb | 98 +++++++++++++++++++---------- 2 files changed, 67 insertions(+), 33 deletions(-) diff --git a/features/cli_receive-events.feature b/features/cli_receive-events.feature index 976e46ce5..5c6546607 100644 --- a/features/cli_receive-events.feature +++ b/features/cli_receive-events.feature @@ -22,7 +22,7 @@ test: Scenario: Running receive-events with no arguments exits uncleanly and shows usage When I run `bundle exec bin/flapjack -n test receiver mirror` Then the exit status should not be 0 - And the output should contain "error: s is required" + And the output should contain "error: d is required, i is required, s is required" #TODO: put some archived events into a separate redis db and then run receive-events to suck them up diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index af650c9f4..0009fe591 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -18,17 +18,26 @@ def initialize(global_options, options) @global_options = global_options @options = options - @config = Flapjack::Configuration.new - @config.load(global_options[:config]) - @config_env = @config.all + if 'mirror'.eql?(@options[:type]) + @config_env = {} + @config_runner = {} + else + @config = Flapjack::Configuration.new + @config.load(global_options[:config]) + @config_env = @config.all + + if @config_env.nil? || @config_env.empty? + exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'" + end - if @config_env.nil? || @config_env.empty? - exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'" + @config_runner = @config_env["#{@options[:type]}-receiver"] || {} end - @config_runner = @config_env["#{@options[:type]}-receiver"] || {} + @redis_options = @config.for_redis + end - @pidfile = case + def pidfile + @pidfile ||= case when !@options[:pidfile].nil? @options[:pidfile] when !@config_env['pid_dir'].nil? @@ -36,8 +45,10 @@ def initialize(global_options, options) else "/var/run/flapjack/#{@options[:type]}-receiver.pid" end + end - @logfile = case + def logfile + @logfile ||= case when !@options[:logfile].nil? @options[:logfile] when !@config_env['log_dir'].nil? @@ -45,8 +56,6 @@ def initialize(global_options, options) else "/var/run/flapjack/#{@options[:type]}-receiver.log" end - - @redis_options = @config.for_redis end def start @@ -95,7 +104,7 @@ def restart def status if runner(@options[:type]).daemon_running? pid = get_pid - uptime = Time.now - File.stat(@pidfile).ctime + uptime = Time.now - File.stat(pidfile).ctime puts "#{@options[:type]}-receiver is running: pid #{pid}, uptime #{uptime}" else exit_now! "#{@options[:type]}-receiver is not running" @@ -107,9 +116,10 @@ def json end def mirror - mirror_receive(:source => @options[:source], - :all => @options[:all], :follow => @options[:follow], - :last => @options[:last], :time => @options[:time]) + mirror_receive(:source => @options[:source], :dest => @options[:dest], + :include => @options[:include], :all => @options[:all], + :follow => @options[:follow], :last => @options[:last], + :time => @options[:time]) end private @@ -121,8 +131,8 @@ def redis def runner(type) return @runner if @runner - @runner = Dante::Runner.new("#{@options[:type]}-receiver", :pid_path => @pidfile, - :log_path => @logfile) + @runner = Dante::Runner.new("#{@options[:type]}-receiver", :pid_path => pidfile, + :log_path => logfile) @runner end @@ -252,7 +262,7 @@ def wait_pid_gone(pid, timeout = 30) end def get_pid - IO.read(@pidfile).chomp.to_i + IO.read(pidfile).chomp.to_i rescue StandardError pid = nil end @@ -330,12 +340,22 @@ def mirror_receive(opts) exit_now! "one or both of --follow or --all is required" end - source_addr = opts[:source] + include_re = nil + begin + include_re = Regexp.new(opts[:include].strip) + rescue RegexpError + exit_now! "could not parse include Regexp: #{opts[:include].strip}" + end + source_addr = opts[:source] source_redis = Redis.new(:url => source_addr, :driver => :hiredis) - refresh_archive_index(source_addr, :redis => source_redis) - archives = mirror_get_archive_keys_stats(source_addr, :redis => source_redis) + dest_addr = opts[:dest] + dest_redis = Redis.new(:url => dest_addr, :driver => :hiredis) + + refresh_archive_index(source_addr, :source => source_redis, :dest => dest_redis) + archives = mirror_get_archive_keys_stats(source_addr, :source => source_redis, + :dest => dest_redis) raise "found no archives!" if archives.empty? puts "found archives: #{archives.inspect}" @@ -364,22 +384,27 @@ def mirror_receive(opts) puts archive_key loop do - event = source_redis.lindex(archive_key, cursor) - if event - Flapjack::Data::Event.add(event, :redis => redis) - events_sent += 1 - print "#{events_sent} " if events_sent % 1000 == 0 + event_json = source_redis.lindex(archive_key, cursor) + if event_json + event = Flapjack::Data::Event.parse_and_validate(event_json) + if !event.nil? && (include_re === "#{event['entity']}:#{event['check']}") + Flapjack::Data::Event.add(event, :redis => dest_redis) + events_sent += 1 + print "#{events_sent} " if events_sent % 1000 == 0 + end cursor -= 1 next end - archives = mirror_get_archive_keys_stats(source_addr, :redis => source_redis) + archives = mirror_get_archive_keys_stats(source_addr, + :source => source_redis, :dest => dest_redis) if archives.any? {|a| a[:size] == 0} # data may be out of date -- refresh, then reject any immediately # expired keys directly; don't keep chasing updated data - refresh_archive_index(source_addr, :redis => source_redis) - archives = mirror_get_archive_keys_stats(source_addr, :redis => source_redis).select {|a| a[:size] > 0} + refresh_archive_index(source_addr, :source => source_redis, :dest => dest_redis) + archives = mirror_get_archive_keys_stats(source_addr, + :source => source_redis, :dest => dest_redis).select {|a| a[:size] > 0} end if archives.empty? @@ -401,14 +426,16 @@ def mirror_receive(opts) end def mirror_get_archive_keys_stats(name, opts = {}) - source_redis = opts[:redis] - redis.smembers("known_events_archive_keys:#{name}").sort.collect do |eak| + source_redis = opts[:source] + dest_redis = opts[:dest] + dest_redis.smembers("known_events_archive_keys:#{name}").sort.collect do |eak| {:name => eak, :size => source_redis.llen(eak)} end end def refresh_archive_index(name, opts = {}) source_redis = opts[:redis] + dest_redis = opts[:dest] # refresh the key name cache, avoid repeated calls to redis KEYS # this cache will be updated any time a new archive bucket is created archive_keys = source_redis.keys("events_archive:*").group_by do |ak| @@ -417,7 +444,7 @@ def refresh_archive_index(name, opts = {}) {'f' => :srem, 't' => :sadd}.each_pair do |k, cmd| next unless archive_keys.has_key?(k) && !archive_keys[k].empty? - redis.send(cmd, "known_events_archive_keys:#{name}", archive_keys[k]) + dest_redis.send(cmd, "known_events_archive_keys:#{name}", archive_keys[k]) end end @@ -618,7 +645,13 @@ def refresh_archive_index(name, opts = {}) receiver.desc 'Mirror receiver' receiver.command :mirror do |mirror| - mirror.flag [:s, 'source'], :desc => 'URL of source redis database, eg redis://localhost:6379/0', + mirror.flag [:s, 'source'], :desc => 'URL of source redis database, e.g. redis://localhost:6379/0', + :required => true + + mirror.flag [:d, 'dest'], :desc => 'URL of destination redis database, e.g. redis://localhost:6379/1', + :required => true + + mirror.flag [:i, 'include'], :desc => 'Regexp which must match event id for it to be mirrored', :required => true # one or both of follow, all is required @@ -637,6 +670,7 @@ def refresh_archive_index(name, opts = {}) :default_value => nil mirror.action do |global_options,options,args| + options.merge!(:type => 'mirror') receiver = Flapjack::CLI::Receiver.new(global_options, options) receiver.mirror end From c74c9a3ef762d85efd4fcaaa6d6a64eefde0b34e Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Wed, 8 Oct 2014 14:50:56 +1030 Subject: [PATCH 33/69] incorporate feedback from @jessereynolds --- features/cli_receive-events.feature | 2 +- lib/flapjack/cli/receiver.rb | 38 +++++++++++++++++++---------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/features/cli_receive-events.feature b/features/cli_receive-events.feature index 5c6546607..976e46ce5 100644 --- a/features/cli_receive-events.feature +++ b/features/cli_receive-events.feature @@ -22,7 +22,7 @@ test: Scenario: Running receive-events with no arguments exits uncleanly and shows usage When I run `bundle exec bin/flapjack -n test receiver mirror` Then the exit status should not be 0 - And the output should contain "error: d is required, i is required, s is required" + And the output should contain "error: s is required" #TODO: put some archived events into a separate redis db and then run receive-events to suck them up diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index 0009fe591..987a2395c 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -18,11 +18,14 @@ def initialize(global_options, options) @global_options = global_options @options = options - if 'mirror'.eql?(@options[:type]) + @config = Flapjack::Configuration.new + + if 'mirror'.eql?(@options[:type]) && + (global_options[:config].nil? || global_options[:config].strip.empty?) + @config_env = {} @config_runner = {} else - @config = Flapjack::Configuration.new @config.load(global_options[:config]) @config_env = @config.all @@ -116,7 +119,14 @@ def json end def mirror - mirror_receive(:source => @options[:source], :dest => @options[:dest], + if (@options[:dest].nil? || @options[:dest].strip.empty?) && + @redis_options.nil? + + exit_now! "No destination redis URL passed, and none configured" + end + + mirror_receive(:source => @options[:source], + :dest => @options[:dest] || @redis_options, :include => @options[:include], :all => @options[:all], :follow => @options[:follow], :last => @options[:last], :time => @options[:time]) @@ -341,10 +351,12 @@ def mirror_receive(opts) end include_re = nil - begin - include_re = Regexp.new(opts[:include].strip) - rescue RegexpError - exit_now! "could not parse include Regexp: #{opts[:include].strip}" + unless opts[:include].nil? || opts[:include].strip.empty? + begin + include_re = Regexp.new(opts[:include].strip) + rescue RegexpError + exit_now! "could not parse include Regexp: #{opts[:include].strip}" + end end source_addr = opts[:source] @@ -387,7 +399,9 @@ def mirror_receive(opts) event_json = source_redis.lindex(archive_key, cursor) if event_json event = Flapjack::Data::Event.parse_and_validate(event_json) - if !event.nil? && (include_re === "#{event['entity']}:#{event['check']}") + if !event.nil? && (include_re.nil? || + (include_re === "#{event['entity']}:#{event['check']}")) + Flapjack::Data::Event.add(event, :redis => dest_redis) events_sent += 1 print "#{events_sent} " if events_sent % 1000 == 0 @@ -434,7 +448,7 @@ def mirror_get_archive_keys_stats(name, opts = {}) end def refresh_archive_index(name, opts = {}) - source_redis = opts[:redis] + source_redis = opts[:source] dest_redis = opts[:dest] # refresh the key name cache, avoid repeated calls to redis KEYS # this cache will be updated any time a new archive bucket is created @@ -648,11 +662,9 @@ def refresh_archive_index(name, opts = {}) mirror.flag [:s, 'source'], :desc => 'URL of source redis database, e.g. redis://localhost:6379/0', :required => true - mirror.flag [:d, 'dest'], :desc => 'URL of destination redis database, e.g. redis://localhost:6379/1', - :required => true + mirror.flag [:d, 'dest'], :desc => 'URL of destination redis database, e.g. redis://localhost:6379/1' - mirror.flag [:i, 'include'], :desc => 'Regexp which must match event id for it to be mirrored', - :required => true + mirror.flag [:i, 'include'], :desc => 'Regexp which must match event id for it to be mirrored' # one or both of follow, all is required mirror.switch [:f, 'follow'], :desc => 'keep reading events as they are archived on the source', From 61539b85ef982617a91b193fcd8eb9761c3371ea Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Wed, 8 Oct 2014 15:05:07 +1030 Subject: [PATCH 34/69] remove source redis known_keys set update from event.rb --- lib/flapjack/data/event.rb | 1 - spec/lib/flapjack/data/event_spec.rb | 18 ------------------ 2 files changed, 19 deletions(-) diff --git a/lib/flapjack/data/event.rb b/lib/flapjack/data/event.rb index feebc8bc5..441c960ae 100755 --- a/lib/flapjack/data/event.rb +++ b/lib/flapjack/data/event.rb @@ -88,7 +88,6 @@ def self.next(queue, opts = {}) raw = redis.rpoplpush(queue, archive_dest) return unless raw end - redis.sadd("known_events_archive_keys", archive_dest) else if options[:block] raw = redis.brpop(queue, 0)[1] diff --git a/spec/lib/flapjack/data/event_spec.rb b/spec/lib/flapjack/data/event_spec.rb index 10e209748..743c2fc94 100644 --- a/spec/lib/flapjack/data/event_spec.rb +++ b/spec/lib/flapjack/data/event_spec.rb @@ -27,8 +27,6 @@ it "returns the next event (blocking, archiving)" do expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(event_data.to_json) - expect(redis).to receive(:sadd). - with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, @@ -48,8 +46,6 @@ it "returns the next event (non-blocking, archiving)" do expect(redis).to receive(:rpoplpush). with('events', /^events_archive:/).and_return(event_data.to_json) - expect(redis).to receive(:sadd). - with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => false, @@ -70,8 +66,6 @@ bad_event_json = '{{{' expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) - expect(redis).to receive(:sadd). - with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) @@ -102,8 +96,6 @@ bad_event_json = bad_event_data.to_json expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) - expect(redis).to receive(:sadd). - with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) @@ -134,8 +126,6 @@ bad_event_json = bad_event_data.to_json expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) - expect(redis).to receive(:sadd). - with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) @@ -168,8 +158,6 @@ bad_event_json = bad_event_data.to_json expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) - expect(redis).to receive(:sadd). - with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) @@ -202,8 +190,6 @@ case_event_data[key] = event_data[key].upcase expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(case_event_data.to_json) - expect(redis).to receive(:sadd). - with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, @@ -230,8 +216,6 @@ num_event_data[key] = event_data[key].to_i.to_s expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(num_event_data.to_json) - expect(redis).to receive(:sadd). - with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, @@ -256,8 +240,6 @@ bad_event_json = bad_event_data.to_json expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) - expect(redis).to receive(:sadd). - with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) From 71ba74775c5973ba651fb5e846c7bcf6d2e957d6 Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Wed, 8 Oct 2014 16:25:26 +1030 Subject: [PATCH 35/69] prepare 1.2.0rc1 release --- CHANGELOG.md | 12 ++++++++++++ Gemfile.lock | 2 +- lib/flapjack/version.rb | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39446317e..7f963a4b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ ## Flapjack Changelog +# 1.2.0rc1 - 2014-10-08 +- Feature: Allow updating an entities name via PATCH /entities/id[,id...] #628 (@ali-graham) +- Feature: Pact specs for flapjack-diner compatability testing #663 (@ali-graham) +- Feature: more api check methods #644 (@ali-graham) +- Chore: optimise tag code #654 (@ali-graham) +- Chore: fix #653, overuse of Redis KEYS in mirror #661 (@ali-graham) +- Bug: Entities should return linked checks with list of check "ids" in API #648 (@ali-graham) +- Bug: 500 error getting all checks from API #641 (@ali-graham) +- Bug: Pager Duty credentials get throws error #657 (@ali-graham) +- Bug: Flapjack crashes when email alert is triggered #656 (@ali-graham) +- Bug: Fix /edit_contacts media saving after adding contacts #651 (@ali-graham) + # 1.1.0 - 2014-09-10 - Feature: Add autorefresh for the web GUI (Closes: #494) #607 (@Hobbsee) - Feature: twilio sms sending #633 (@jessereynolds) diff --git a/Gemfile.lock b/Gemfile.lock index a06b646f5..bc7d226e3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - flapjack (1.1.0) + flapjack (1.2.0rc1) activesupport (~> 3.2.14) blather (~> 0.8.3) chronic diff --git a/lib/flapjack/version.rb b/lib/flapjack/version.rb index 511bd49c2..027b20afc 100644 --- a/lib/flapjack/version.rb +++ b/lib/flapjack/version.rb @@ -1,6 +1,6 @@ #!/usr/bin/env ruby module Flapjack - VERSION = "1.1.0" + VERSION = "1.2.0rc1" end From 8f55621a9ca8253c899b0c559f705fff99cba818 Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Wed, 8 Oct 2014 17:10:59 +1030 Subject: [PATCH 36/69] prepare 1.2.0rc1 release for ruby 1.9 --- Gemfile-ruby1.9.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Gemfile-ruby1.9.lock b/Gemfile-ruby1.9.lock index a4c62171f..0c6beb925 100644 --- a/Gemfile-ruby1.9.lock +++ b/Gemfile-ruby1.9.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - flapjack (1.1.0) + flapjack (1.2.0rc1) activesupport (~> 3.2.14) blather (~> 0.8.3) chronic @@ -122,9 +122,9 @@ GEM mail (2.6.1) mime-types (>= 1.16, < 3) method_source (0.8.2) - mime-types (2.3) + mime-types (2.4.1) mini_portile (0.6.0) - msgpack (0.5.8) + msgpack (0.5.9) multi_json (1.10.1) multi_test (0.1.1) niceogiri (1.1.2) @@ -132,7 +132,7 @@ GEM nokogiri (1.6.2.1) mini_portile (= 0.6.0) numerizer (0.1.1) - oj (2.10.2) + oj (2.10.3) pact (1.3.3) awesome_print (~> 1.1) find_a_port (~> 1.0.1) @@ -207,10 +207,10 @@ GEM term-ansicolor (1.3.0) tins (~> 1.0) terminal-table (1.4.5) - thin (1.6.2) - daemons (>= 1.0.9) - eventmachine (>= 1.0.0) - rack (>= 1.0.0) + thin (1.6.3) + daemons (~> 1.0, >= 1.0.9) + eventmachine (~> 1.0) + rack (~> 1.0) thor (0.19.1) tilt (1.4.1) timers (4.0.1) @@ -218,7 +218,7 @@ GEM tins (1.3.3) trollop (2.0) tzinfo (1.0.1) - tzinfo-data (1.2014.7) + tzinfo-data (1.2014.8) tzinfo (>= 1.0.0) vegas (0.1.11) rack (>= 1.0.0) From 2a59cecd9be6c0286c6616b99a851d723ec72dee Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Thu, 9 Oct 2014 13:04:02 +1030 Subject: [PATCH 37/69] fix mirror options handling --- lib/flapjack/cli/receiver.rb | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index 987a2395c..3e73ccac4 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -19,20 +19,17 @@ def initialize(global_options, options) @options = options @config = Flapjack::Configuration.new + @config.load(global_options[:config]) + @config_env = @config.all - if 'mirror'.eql?(@options[:type]) && - (global_options[:config].nil? || global_options[:config].strip.empty?) + if @config_env.nil? || @config_env.empty? + unless 'mirror'.eql?(@options[:type]) + exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'" + end @config_env = {} @config_runner = {} else - @config.load(global_options[:config]) - @config_env = @config.all - - if @config_env.nil? || @config_env.empty? - exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'" - end - @config_runner = @config_env["#{@options[:type]}-receiver"] || {} end From deb2aa01e7b0046a9cf7731d14ac8882cc0b63a7 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Thu, 9 Oct 2014 13:16:54 +1030 Subject: [PATCH 38/69] fix mirror redis init --- lib/flapjack/cli/receiver.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index 3e73ccac4..433cbf1cf 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -360,7 +360,14 @@ def mirror_receive(opts) source_redis = Redis.new(:url => source_addr, :driver => :hiredis) dest_addr = opts[:dest] - dest_redis = Redis.new(:url => dest_addr, :driver => :hiredis) + dest_redis = case dest_addr + when Hash + Redis.new(dest_redis.merge(:driver => :hiredis)) + when String + Redis.new(:url => dest_addr, :driver => :hiredis) + else + exit_now! "could not understand destination Redis config" + end refresh_archive_index(source_addr, :source => source_redis, :dest => dest_redis) archives = mirror_get_archive_keys_stats(source_addr, :source => source_redis, From feb1073f9cbbbd28eca29307b92b26a6f633445d Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Thu, 9 Oct 2014 13:20:17 +1030 Subject: [PATCH 39/69] typo --- lib/flapjack/cli/receiver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index 433cbf1cf..cb8776417 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -362,7 +362,7 @@ def mirror_receive(opts) dest_addr = opts[:dest] dest_redis = case dest_addr when Hash - Redis.new(dest_redis.merge(:driver => :hiredis)) + Redis.new(dest_addr.merge(:driver => :hiredis)) when String Redis.new(:url => dest_addr, :driver => :hiredis) else From a5ff3d5778bc3032d4fa6b72cafc9e980e8705e1 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 10 Oct 2014 10:12:29 +1030 Subject: [PATCH 40/69] jsonapi - remove tags from contact PATCH, add them to check GET --- lib/flapjack/data/entity_check.rb | 1 + .../gateways/jsonapi/contact_methods.rb | 6 - .../pacts/flapjack-diner_v1.0.json | 5146 ++++++++--------- 3 files changed, 2574 insertions(+), 2579 deletions(-) diff --git a/lib/flapjack/data/entity_check.rb b/lib/flapjack/data/entity_check.rb index 3c248d308..d5beb37bf 100755 --- a/lib/flapjack/data/entity_check.rb +++ b/lib/flapjack/data/entity_check.rb @@ -977,6 +977,7 @@ def to_jsonapi(opts = {}) "name" => @check, "entity_name" => @entity.name, "enabled" => opts[:enabled].is_a?(TrueClass), + "tags" => self.tags.to_a, "links" => { :entities => opts[:entity_ids] || [], } diff --git a/lib/flapjack/gateways/jsonapi/contact_methods.rb b/lib/flapjack/gateways/jsonapi/contact_methods.rb index 11f9da0d7..86c326b1d 100644 --- a/lib/flapjack/gateways/jsonapi/contact_methods.rb +++ b/lib/flapjack/gateways/jsonapi/contact_methods.rb @@ -144,9 +144,6 @@ def self.registered(app) unless notification_rule.nil? contact.grab_notification_rule(notification_rule) end - when 'tags' - value.respond_to?(:each) ? contact.add_tags(*value) : - contact.add_tags(value) # when 'media' # not supported yet due to id brokenness end when 'remove' @@ -159,9 +156,6 @@ def self.registered(app) unless notification_rule.nil? contact.delete_notification_rule(notification_rule) end - when 'tags' - value.respond_to?(:each) ? contact.delete_tags(*value) : - contact.delete_tags(value) # when 'media' # not supported yet due to id brokenness end end diff --git a/spec/service_consumers/pacts/flapjack-diner_v1.0.json b/spec/service_consumers/pacts/flapjack-diner_v1.0.json index d3ec2c617..1e631021e 100644 --- a/spec/service_consumers/pacts/flapjack-diner_v1.0.json +++ b/spec/service_consumers/pacts/flapjack-diner_v1.0.json @@ -7,83 +7,73 @@ }, "interactions": [ { - "description": "a GET request for a downtime report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one set of pagerduty credentials", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "get", - "path": "/downtime_report/checks" - }, - "response": { - "status": 200, + "method": "post", + "path": "/contacts/abc/pagerduty_credentials", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "downtime_reports": [ + "pagerduty_credentials": [ { + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc" + ] } }, { - "description": "a GET request for a outage report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one set of pagerduty credentials", + "provider_state": "no contact exists", "request": { - "method": "get", - "path": "/outage_report/entities/1234" - }, - "response": { - "status": 200, + "method": "post", + "path": "/contacts/abc/pagerduty_credentials", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "outage_reports": [ + "pagerduty_credentials": [ { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } - } - }, - { - "description": "a time limited GET request for a downtime report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "get", - "path": "/downtime_report/entities", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { - "status": 200, + "status": 422, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ - { - } + "errors": [ + "Contact id: 'abc' could not be loaded" ] } } }, { - "description": "a GET request for a scheduled_maintenance report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for all pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { "method": "get", - "path": "/scheduled_maintenance_report/entities/1234,5678" + "path": "/pagerduty_credentials" }, "response": { "status": 200, @@ -91,44 +81,23 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ - { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - }, + "pagerduty_credentials": [ { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } } }, { - "description": "a time limited GET request for a downtime report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for one set of pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { "method": "get", - "path": "/downtime_report/checks", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" + "path": "/pagerduty_credentials/abc" }, "response": { "status": 200, @@ -136,20 +105,23 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ + "pagerduty_credentials": [ { + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" } ] } } }, { - "description": "a time limited GET request for a scheduled_maintenance report on a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for two sets of pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", "request": { "method": "get", - "path": "/scheduled_maintenance_report/checks/www.example.com:SSH", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" + "path": "/pagerduty_credentials/abc,872" }, "response": { "status": 200, @@ -157,1239 +129,976 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "pagerduty_credentials": [ { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "service_key": "abc", + "subdomain": "def", + "username": "ghi", + "password": "jkl" + }, + { + "service_key": "mno", + "subdomain": "pqr", + "username": "stu", + "password": "vwx" } ] } } }, { - "description": "a GET request for a unscheduled_maintenance report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for one set of pagerduty credentials", + "provider_state": "no contact exists", "request": { "method": "get", - "path": "/unscheduled_maintenance_report/entities/1234" + "path": "/pagerduty_credentials/abc" }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } + "errors": [ + "could not find contact 'abc'" ] } } }, { - "description": "a time limited GET request for a outage report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request for pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { - "method": "get", - "path": "/outage_report/checks", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" + "method": "patch", + "path": "/pagerduty_credentials/abc", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" + } + ] }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", + "request": { + "method": "patch", + "path": "/pagerduty_credentials/abc,872", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, - "body": { - "outage_reports": [ - { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } - ] - } + "body": [ + { + "op": "replace", + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" + } + ] + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a time limited GET request for a unscheduled_maintenance report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a PATCH request for pagerduty credentials", + "provider_state": "no contact exists", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/entities/1234,5678", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" + "method": "patch", + "path": "/pagerduty_credentials/abc", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/pagerduty_credentials/0/password", + "value": "pswrd" + } + ] }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - }, - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } - } + "errors": [ + "could not find contact 'abc'" ] } } }, { - "description": "a GET request for a scheduled_maintenance report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a DELETE request for one set of pagerduty credentials", + "provider_state": "a contact with id 'abc' has pagerduty credentials", "request": { - "method": "get", - "path": "/scheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING" + "method": "delete", + "path": "/pagerduty_credentials/abc", + "body": null }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "scheduled_maintenance_reports": [ - { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - }, - { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a time-limited GET request for a unscheduled_maintenance report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a DELETE request for two sets of pagerduty credentials", + "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" + "method": "delete", + "path": "/pagerduty_credentials/abc,872", + "body": null }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - }, - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a time limited GET request for a unscheduled_maintenance report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for one set of pagerduty credentials", + "provider_state": "no contact exists", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/entities/1234", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" + "method": "delete", + "path": "/pagerduty_credentials/abc", + "body": null }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } + "errors": [ + "could not find contact 'abc'" ] } } }, { - "description": "a time limited GET request for a outage report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/outage_report/entities/1234", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "outage_reports": [ + "scheduled_maintenances": [ { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "start_time": "2014-10-10T09:38:02+10:30", + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a status report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "no entity exists", "request": { - "method": "get", - "path": "/status_report/checks" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "status_reports": [ + "scheduled_maintenances": [ { + "start_time": "2014-10-10T09:38:02+10:30", + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity '1234'" + ] + } } }, { - "description": "a GET request for a downtime report on a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/downtime_report/checks/www.example.com:SSH" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "downtime_reports": [ + "scheduled_maintenances": [ { + "start_time": "2014-10-10T09:38:02+10:30", + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a status report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/status_report/checks/www.example.com:SSH,www2.example.com:PING" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "status_reports": [ + "scheduled_maintenances": [ { + "start_time": "2014-10-10T09:38:02+10:30", + "duration": 3600, + "summary": "working" }, { + "start_time": "2014-10-10T11:38:02+10:30", + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a scheduled_maintenance report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/scheduled_maintenance_report/entities/1234" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenance_reports": [ + "scheduled_maintenances": [ { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "start_time": "2014-10-10T09:38:03+10:30", + "duration": 3600, + "summary": "working" + }, + { + "start_time": "2014-10-10T11:38:03+10:30", + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a time limited GET request for a scheduled_maintenance report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/scheduled_maintenance_report/checks", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenance_reports": [ + "unscheduled_maintenances": [ { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a time limited GET request for a scheduled_maintenance report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "no entity exists", "request": { - "method": "get", - "path": "/scheduled_maintenance_report/entities/1234,5678", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenance_reports": [ - { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - }, + "unscheduled_maintenances": [ { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } + "duration": 3600, + "summary": "working" } ] } - } - }, - { - "description": "a GET request for a downtime report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", - "request": { - "method": "get", - "path": "/downtime_report/entities/1234,5678" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, + "status": 404, "body": { - "downtime_reports": [ - { - }, - { - } + "errors": [ + "could not find entity '1234'" ] } } }, { - "description": "a GET request for a unscheduled_maintenance report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/checks" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenance_reports": [ + "unscheduled_maintenances": [ { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a time limited GET request for a outage report on a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/outage_report/checks/www.example.com:SSH", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "outage_reports": [ + "unscheduled_maintenances": [ { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a scheduled_maintenance report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/scheduled_maintenance_report/entities" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenance_reports": [ + "unscheduled_maintenances": [ { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a unscheduled_maintenance report on a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH" + "method": "patch", + "path": "/unscheduled_maintenances/entities/1234", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-10-10T09:38:03+10:30" + } + ] }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/entities/1234,5678", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, - "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } - ] - } + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-10-10T09:38:03+10:30" + } + ] + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a time limited GET request for a downtime report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no entity exists", "request": { - "method": "get", - "path": "/downtime_report/entities/1234,5678", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" - }, - "response": { - "status": 200, + "method": "patch", + "path": "/unscheduled_maintenances/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-10-10T09:38:03+10:30" + } + ] + }, + "response": { + "status": 404, "body": { - "downtime_reports": [ - { - }, - { - } + "errors": [ + "could not find entity '1234'" ] } } }, { - "description": "a GET request for a scheduled_maintenance report on a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/scheduled_maintenance_report/checks/www.example.com:SSH" + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-10-10T09%3A38%3A03%2B10%3A30" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "scheduled_maintenance_reports": [ - { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a time limited GET request for a downtime report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { - "method": "get", - "path": "/downtime_report/entities/1234", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" + "method": "delete", + "path": "/scheduled_maintenances/entities/1234,5678", + "query": "start_time=2014-10-10T09%3A38%3A03%2B10%3A30" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "downtime_reports": [ - { - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a GET request for a status report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no entity exists", "request": { - "method": "get", - "path": "/status_report/entities" + "method": "delete", + "path": "/scheduled_maintenances/entities/1234", + "query": "start_time=2014-10-10T09%3A38%3A03%2B10%3A30" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, + "status": 404, "body": { - "status_reports": [ - { - } + "errors": [ + "could not find entity '1234'" ] } } }, { - "description": "a GET request for a scheduled_maintenance report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "get", - "path": "/scheduled_maintenance_report/checks" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "scheduled_maintenance_reports": [ + "scheduled_maintenances": [ { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "start_time": "2014-10-10T09:38:03+10:30", + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a outage report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a POST request with one scheduled maintenance period", + "provider_state": "no check exists", "request": { - "method": "get", - "path": "/outage_report/checks/www.example.com:SSH,www2.example.com:PING" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "outage_reports": [ - { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - }, + "scheduled_maintenances": [ { - "outages": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } + "start_time": "2014-10-10T09:38:03+10:30", + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { - "description": "a time limited GET request for a unscheduled_maintenance report on all checks", + "description": "a POST request with one scheduled maintenance period", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/checks", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenance_reports": [ + "scheduled_maintenances": [ { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "start_time": "2014-10-10T09:38:03+10:30", + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a status report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a POST request with two scheduled maintenance periods", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/status_report/entities/1234,5678" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "status_reports": [ + "scheduled_maintenances": [ { + "start_time": "2014-10-10T09:38:03+10:30", + "duration": 3600, + "summary": "working" }, { + "start_time": "2014-10-10T11:38:03+10:30", + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a time-limited GET request for a outage report on two checks", + "description": "a POST request with two scheduled maintenance periods", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "get", - "path": "/outage_report/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" - }, - "response": { - "status": 200, + "method": "post", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "outage_reports": [ + "scheduled_maintenances": [ { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "start_time": "2014-10-10T09:38:03+10:30", + "duration": 3600, + "summary": "working" }, { - "outages": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } + "start_time": "2014-10-10T11:38:03+10:30", + "duration": 3600, + "summary": "more work" } ] } - } - }, - { - "description": "a time limited GET request for a scheduled_maintenance report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "get", - "path": "/scheduled_maintenance_report/entities", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "scheduled_maintenance_reports": [ - { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a GET request for a unscheduled_maintenance report on two entities", + "description": "a POST request with one unscheduled maintenance period", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/entities/1234,5678" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - }, + "unscheduled_maintenances": [ { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a downtime report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one unscheduled maintenance period", + "provider_state": "no check exists", "request": { - "method": "get", - "path": "/downtime_report/entities/1234" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "downtime_reports": [ + "unscheduled_maintenances": [ { + "duration": 3600, + "summary": "working" } ] } - } - }, - { - "description": "a GET request for a unscheduled_maintenance report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/entities" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, + "status": 404, "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } + "errors": [ + "could not find entity 'www.example.com'" ] } } }, { - "description": "a time limited GET request for a outage report on all entities", + "description": "a POST request with one unscheduled maintenance period", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/outage_report/entities", - "query": "start_time=2014-10-02T21%3A10%3A16%2B09%3A30&end_time=2014-10-03T09%3A10%3A16%2B09%3A30" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "outage_reports": [ + "unscheduled_maintenances": [ { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "duration": 3600, + "summary": "working" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a outage report on a single check", + "description": "a POST request with two unscheduled maintenance periods", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/outage_report/checks/www.example.com:SSH" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "outage_reports": [ + "unscheduled_maintenances": [ { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "duration": 3600, + "summary": "working" + }, + { + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a status report on a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with two unscheduled maintenance periods", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "get", - "path": "/status_report/checks/www.example.com:SSH" - }, - "response": { - "status": 200, + "method": "post", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "status_reports": [ + "unscheduled_maintenances": [ + { + "duration": 3600, + "summary": "working" + }, { + "duration": 3600, + "summary": "more work" } ] } + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a GET request for a unscheduled_maintenance report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING" - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/json-patch+json" }, - "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - }, - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } - } - ] - } + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-10-10T09:38:03+10:30" + } + ] + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a time limited GET request for a scheduled_maintenance report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "get", - "path": "/scheduled_maintenance_report/entities/1234", - "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30&end_time=2014-10-03T09%3A10%3A17%2B09%3A30" + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-10-10T09:38:03+10:30" + } + ] }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a PATCH request for an unscheduled maintenance period", + "provider_state": "no check exists", + "request": { + "method": "patch", + "path": "/unscheduled_maintenances/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, + "body": [ + { + "op": "replace", + "path": "/unscheduled_maintenances/0/end_time", + "value": "2014-10-10T09:38:03+10:30" + } + ] + }, + "response": { + "status": 404, "body": { - "scheduled_maintenance_reports": [ - { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } + "errors": [ + "could not find entity 'www.example.com'" ] } } }, { - "description": "a GET request for a outage report on all entities", + "description": "a DELETE request for a scheduled maintenance period", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "get", - "path": "/outage_report/entities" + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-10-10T09%3A38%3A03%2B10%3A30" }, "response": { - "status": 200, + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-10-10T09%3A38%3A03%2B10%3A30" + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a scheduled maintenance period", + "provider_state": "no check exists", + "request": { + "method": "delete", + "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "query": "start_time=2014-10-10T09%3A38%3A03%2B10%3A30" + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } + } + }, + { + "description": "a POST request with one entity", + "provider_state": "no entity exists", + "request": { + "method": "post", + "path": "/entities", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "outage_reports": [ + "entities": [ { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "name": "example.org", + "id": "57_example" } ] } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example" + ] } }, { - "description": "a GET request for a outage report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a POST request with two entities", + "provider_state": "no entity exists", "request": { - "method": "get", - "path": "/outage_report/entities/1234,5678" - }, - "response": { - "status": 200, + "method": "post", + "path": "/entities", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "outage_reports": [ + "entities": [ { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "name": "example.org", + "id": "57_example" }, { - "outages": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } + "name": "example2.org", + "id": "58" } ] } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "57_example", + "58" + ] } }, { - "description": "a time limited GET request for a downtime report on a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a GET request for all entities", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "get", - "path": "/downtime_report/checks/www.example.com:SSH", - "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30&end_time=2014-10-03T09%3A10%3A17%2B09%3A30" + "path": "/entities" }, "response": { "status": 200, @@ -1397,20 +1106,21 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ + "entities": [ { + "name": "www.example.com", + "id": "1234" } ] } } }, { - "description": "a time-limited GET request for a downtime report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for all entities", + "provider_state": "no entity exists", "request": { "method": "get", - "path": "/downtime_report/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30&end_time=2014-10-03T09%3A10%3A17%2B09%3A30" + "path": "/entities" }, "response": { "status": 200, @@ -1418,22 +1128,18 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ - { - }, - { - } + "entities": [ + ] } } }, { - "description": "a time-limited GET request for a scheduled_maintenance report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "get", - "path": "/scheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30&end_time=2014-10-03T09%3A10%3A17%2B09%3A30" + "path": "/entities/1234" }, "response": { "status": 200, @@ -1441,245 +1147,190 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenance_reports": [ + "entities": [ { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - }, - { - "scheduled_maintenances": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } + "name": "www.example.com", + "id": "1234" } ] } } }, { - "description": "a time limited GET request for a outage report on two entities", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a single entity", + "provider_state": "no entity exists", "request": { "method": "get", - "path": "/outage_report/entities/1234,5678", - "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30&end_time=2014-10-03T09%3A10%3A17%2B09%3A30" + "path": "/entities/1234" }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "outage_reports": [ - { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - }, - { - "outages": [ - - ], - "links": { - "entity": [ - "5678" - ], - "check": [ - "www2.example.com:PING" - ] - } - } + "errors": [ + "could not find entities: '1234'" ] } } }, { - "description": "a GET request for a status report on one entity", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request for a single entity", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { - "method": "get", - "path": "/status_report/entities/1234" - }, - "response": { - "status": 200, + "method": "patch", + "path": "/entities/1234", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/json-patch+json" }, - "body": { - "status_reports": [ - { - } - ] - } + "body": [ + { + "op": "replace", + "path": "/entities/0/name", + "value": "example3.com" + } + ] + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a time limited GET request for a unscheduled_maintenance report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a PATCH request for a single entity", + "provider_state": "no entity exists", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/entities", - "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30&end_time=2014-10-03T09%3A10%3A17%2B09%3A30" + "method": "patch", + "path": "/entities/1234", + "headers": { + "Content-Type": "application/json-patch+json" + }, + "body": [ + { + "op": "replace", + "path": "/entities/0/name", + "value": "example3.com" + } + ] }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenance_reports": [ - { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } - } + "errors": [ + "could not find entity '1234'" ] } } }, { - "description": "a time limited GET request for a unscheduled_maintenance report on a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one medium", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "get", - "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH", - "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30&end_time=2014-10-03T09%3A10%3A17%2B09%3A30" - }, - "response": { - "status": 200, + "method": "post", + "path": "/contacts/abc/media", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "unscheduled_maintenance_reports": [ + "media": [ { - "unscheduled_maintenances": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 } ] } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc_sms" + ] } }, { - "description": "a GET request for a downtime report on two checks", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a POST request with two media", + "provider_state": "a contact with id 'abc' exists", "request": { - "method": "get", - "path": "/downtime_report/checks/www.example.com:SSH,www2.example.com:PING" - }, - "response": { - "status": 200, + "method": "post", + "path": "/contacts/abc/media", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "downtime_reports": [ + "media": [ { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 }, { + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3 } ] } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc_sms", + "abc_email" + ] } }, { - "description": "a GET request for a outage report on all checks", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a POST request with one medium", + "provider_state": "no contact exists", "request": { - "method": "get", - "path": "/outage_report/checks" - }, - "response": { - "status": 200, + "method": "post", + "path": "/contacts/abc/media", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "outage_reports": [ + "media": [ { - "outages": [ - - ], - "links": { - "entity": [ - "1234" - ], - "check": [ - "www.example.com:SSH" - ] - } + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5 } ] } - } - }, - { - "description": "a GET request for a downtime report on all entities", - "provider_state": "a check 'www.example.com:SSH' exists", - "request": { - "method": "get", - "path": "/downtime_report/entities" }, "response": { - "status": 200, + "status": 422, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "downtime_reports": [ - { - } + "errors": [ + "Contact id: 'abc' could not be loaded" ] } } }, { - "description": "a GET request for one set of pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", + "description": "a GET request for all media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "get", - "path": "/pagerduty_credentials/abc" + "path": "/media" }, "response": { "status": 200, @@ -1687,42 +1338,39 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "pagerduty_credentials": [ + "media": [ { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" - } - ] - } - } - }, - { - "description": "a GET request for one set of pagerduty credentials", - "provider_state": "no contact exists", - "request": { - "method": "get", - "path": "/pagerduty_credentials/abc" - }, - "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find contact 'abc'" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3, + "links": { + "contacts": [ + "abc" + ] + } + }, + { + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } + } ] } } }, { - "description": "a GET request for all pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", + "description": "a GET request for sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "get", - "path": "/pagerduty_credentials" + "path": "/media/abc_sms" }, "response": { "status": 200, @@ -1730,23 +1378,28 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "pagerduty_credentials": [ + "media": [ { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } } ] } } }, { - "description": "a GET request for two sets of pagerduty credentials", - "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", + "description": "a GET request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "get", - "path": "/pagerduty_credentials/abc,872" + "path": "/media/abc_email,abc_sms" }, "response": { "status": 200, @@ -1754,56 +1407,39 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "pagerduty_credentials": [ + "media": [ { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" + "type": "email", + "address": "ablated@example.org", + "interval": 180, + "rollup_threshold": 3, + "links": { + "contacts": [ + "abc" + ] + } }, { - "service_key": "mno", - "subdomain": "pqr", - "username": "stu", - "password": "vwx" + "type": "sms", + "address": "0123456789", + "interval": 300, + "rollup_threshold": 5, + "links": { + "contacts": [ + "abc" + ] + } } ] } } }, { - "description": "a DELETE request for one set of pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", - "request": { - "method": "delete", - "path": "/pagerduty_credentials/abc", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for two sets of pagerduty credentials", - "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", - "request": { - "method": "delete", - "path": "/pagerduty_credentials/abc,872", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for one set of pagerduty credentials", + "description": "a GET request for sms media", "provider_state": "no contact exists", "request": { - "method": "delete", - "path": "/pagerduty_credentials/abc", - "body": null + "method": "get", + "path": "/media/abc_sms" }, "response": { "status": 404, @@ -1818,81 +1454,24 @@ } }, { - "description": "a POST request with one set of pagerduty credentials", - "provider_state": "no contact exists", - "request": { - "method": "post", - "path": "/contacts/abc/pagerduty_credentials", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "pagerduty_credentials": [ - { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" - } - ] - } - }, - "response": { - "status": 422, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "Contact id: 'abc' could not be loaded" - ] - } - } - }, - { - "description": "a POST request with one set of pagerduty credentials", - "provider_state": "a contact with id 'abc' exists", - "request": { - "method": "post", - "path": "/contacts/abc/pagerduty_credentials", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "pagerduty_credentials": [ - { - "service_key": "abc", - "subdomain": "def", - "username": "ghi", - "password": "jkl" - } - ] - } - }, - "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "abc" - ] - } - }, - { - "description": "a PATCH request for pagerduty credentials", - "provider_state": "a contact with id 'abc' has pagerduty credentials", + "description": "a PATCH request for email media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "patch", - "path": "/pagerduty_credentials/abc", + "path": "/media/abc_email", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/pagerduty_credentials/0/password", - "value": "pswrd" + "path": "/media/0/interval", + "value": 50 + }, + { + "op": "replace", + "path": "/media/0/rollup_threshold", + "value": 3 } ] }, @@ -1902,19 +1481,24 @@ } }, { - "description": "a PATCH request for pagerduty credentials", - "provider_state": "contacts with ids 'abc' and '872' have pagerduty credentials", + "description": "a PATCH request for email and sms media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { "method": "patch", - "path": "/pagerduty_credentials/abc,872", + "path": "/media/abc_email,abc_sms", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/pagerduty_credentials/0/password", - "value": "pswrd" + "path": "/media/0/interval", + "value": 50 + }, + { + "op": "replace", + "path": "/media/0/rollup_threshold", + "value": 3 } ] }, @@ -1924,19 +1508,19 @@ } }, { - "description": "a PATCH request for pagerduty credentials", + "description": "a PATCH request for email media", "provider_state": "no contact exists", "request": { "method": "patch", - "path": "/pagerduty_credentials/abc", + "path": "/media/abc_email", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/pagerduty_credentials/0/password", - "value": "pswrd" + "path": "/media/0/interval", + "value": 50 } ] }, @@ -1953,22 +1537,12 @@ } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a DELETE request for one medium", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } - ] - } + "method": "delete", + "path": "/media/abc_email", + "body": null }, "response": { "status": 204, @@ -1976,736 +1550,962 @@ } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "no check exists", + "description": "a DELETE request for two media", + "provider_state": "a contact with id 'abc' has email and sms media", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - } - ] - } + "method": "delete", + "path": "/media/abc_email,abc_sms", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for one medium", + "provider_state": "no contact exists", + "request": { + "method": "delete", + "path": "/media/abc_email", + "body": null }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find contact 'abc'" ] } } }, { - "description": "a POST request with one unscheduled maintenance period", + "description": "a GET request for a unscheduled_maintenance report on one entity", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/unscheduled_maintenance_report/entities/1234" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "unscheduled_maintenance_reports": [ { - "duration": 3600, - "summary": "working" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a unscheduled_maintenance report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "method": "get", + "path": "/unscheduled_maintenance_report/checks" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, + "unscheduled_maintenance_reports": [ { - "duration": 3600, - "summary": "more work" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a time-limited GET request for a scheduled_maintenance report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-10-10T09%3A38%3A04%2B10%3A30&end_time=2014-10-10T21%3A38%3A04%2B10%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "scheduled_maintenance_reports": [ { - "duration": 3600, - "summary": "working" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } }, { - "duration": 3600, - "summary": "more work" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a GET request for a downtime report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "method": "get", + "path": "/downtime_report/checks" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "downtime_reports": [ { - "start_time": "2014-10-02T21:10:17+09:30", - "duration": 3600, - "summary": "working" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "no check exists", + "description": "a GET request for a status report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/status_report/entities/1234" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "status_reports": [ { - "start_time": "2014-10-02T21:10:17+09:30", - "duration": 3600, - "summary": "working" } ] } - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity 'www.example.com'" - ] - } } }, { - "description": "a POST request with one scheduled maintenance period", + "description": "a GET request for a unscheduled_maintenance report on all entities", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/unscheduled_maintenance_report/entities" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "unscheduled_maintenance_reports": [ { - "start_time": "2014-10-02T21:10:17+09:30", - "duration": 3600, - "summary": "working" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", + "description": "a GET request for a downtime report on two entities", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", + "method": "get", + "path": "/downtime_report/entities/1234,5678" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "downtime_reports": [ { - "start_time": "2014-10-02T21:10:17+09:30", - "duration": 3600, - "summary": "working" }, { - "start_time": "2014-10-02T23:10:17+09:30", - "duration": 3600, - "summary": "more work" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", + "description": "a time limited GET request for a unscheduled_maintenance report on all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", + "method": "get", + "path": "/unscheduled_maintenance_report/checks", + "query": "start_time=2014-10-10T09%3A38%3A04%2B10%3A30&end_time=2014-10-10T21%3A38%3A04%2B10%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-10-02T21:10:17+09:30", - "duration": 3600, - "summary": "working" - }, + "unscheduled_maintenance_reports": [ { - "start_time": "2014-10-02T23:10:17+09:30", - "duration": 3600, - "summary": "more work" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } + } + }, + { + "description": "a GET request for a unscheduled_maintenance report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "get", + "path": "/unscheduled_maintenance_report/entities/1234,5678" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "unscheduled_maintenance_reports": [ + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } + } + ] + } } }, { - "description": "a PATCH request for an unscheduled maintenance period", + "description": "a GET request for a scheduled_maintenance report on a single check", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-10-02T21:10:17+09:30" - } - ] + "method": "get", + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } + ] + } } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a time limited GET request for a scheduled_maintenance report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-10-02T21:10:17+09:30" - } - ] + "method": "get", + "path": "/scheduled_maintenance_report/entities/1234", + "query": "start_time=2014-10-10T09%3A38%3A04%2B10%3A30&end_time=2014-10-10T21%3A38%3A04%2B10%3A30" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } + ] + } } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no check exists", + "description": "a GET request for a scheduled_maintenance report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-10-02T21:10:17+09:30" - } - ] + "method": "get", + "path": "/scheduled_maintenance_report/checks" }, "response": { - "status": 404, + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { - "errors": [ - "could not find entity 'www.example.com'" + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } ] } } }, { - "description": "a DELETE request for a scheduled maintenance period", + "description": "a GET request for a scheduled_maintenance report on one entity", "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30" + "method": "get", + "path": "/scheduled_maintenance_report/entities/1234" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } + ] + } } }, { - "description": "a DELETE request for a scheduled maintenance period", + "description": "a GET request for a scheduled_maintenance report on two entities", "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH,www2.example.com:PING", - "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30" + "method": "get", + "path": "/scheduled_maintenance_report/entities/1234,5678" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } + } + ] + } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no check exists", + "description": "a GET request for a status report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "delete", - "path": "/scheduled_maintenances/checks/www.example.com:SSH", - "query": "start_time=2014-10-02T21%3A10%3A17%2B09%3A30" + "method": "get", + "path": "/status_report/checks/www.example.com:SSH" }, "response": { - "status": 404, + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { - "errors": [ - "could not find entity 'www.example.com'" + "status_reports": [ + { + } ] } } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a time limited GET request for a downtime report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "method": "get", + "path": "/downtime_report/entities", + "query": "start_time=2014-10-10T09%3A38%3A04%2B10%3A30&end_time=2014-10-10T21%3A38%3A04%2B10%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "downtime_reports": [ { - "duration": 3600, - "summary": "working" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "no entity exists", + "description": "a GET request for a status report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "method": "get", + "path": "/status_report/entities/1234,5678" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "status_reports": [ + { + }, { - "duration": 3600, - "summary": "working" } ] } + } + }, + { + "description": "a GET request for a outage report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "get", + "path": "/outage_report/checks/www.example.com:SSH,www2.example.com:PING" }, "response": { - "status": 404, + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { - "errors": [ - "could not find entity '1234'" + "outage_reports": [ + { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "outages": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } + } ] } } }, { - "description": "a POST request with one unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a time-limited GET request for a unscheduled_maintenance report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "method": "get", + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-10-10T09%3A38%3A04%2B10%3A30&end_time=2014-10-10T21%3A38%3A04%2B10%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ + "unscheduled_maintenance_reports": [ { - "duration": 3600, - "summary": "working" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for a downtime report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234,5678", + "method": "get", + "path": "/downtime_report/checks/www.example.com:SSH" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, + "downtime_reports": [ { - "duration": 3600, - "summary": "more work" } ] } + } + }, + { + "description": "a time limited GET request for a outage report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/outage_report/entities/1234", + "query": "start_time=2014-10-10T09%3A38%3A04%2B10%3A30&end_time=2014-10-10T21%3A38%3A04%2B10%3A30" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "outage_reports": [ + { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } + ] + } } }, { - "description": "a POST request with two unscheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a time limited GET request for a unscheduled_maintenance report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/unscheduled_maintenances/entities/1234", + "method": "get", + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH", + "query": "start_time=2014-10-10T09%3A38%3A04%2B10%3A30&end_time=2014-10-10T21%3A38%3A04%2B10%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "unscheduled_maintenances": [ - { - "duration": 3600, - "summary": "working" - }, + "unscheduled_maintenance_reports": [ { - "duration": 3600, - "summary": "more work" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a time limited GET request for a outage report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "method": "get", + "path": "/outage_report/checks", + "query": "start_time=2014-10-10T09%3A38%3A04%2B10%3A30&end_time=2014-10-10T21%3A38%3A04%2B10%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "outage_reports": [ { - "start_time": "2014-10-02T21:10:18+09:30", - "duration": 3600, - "summary": "working" + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "no entity exists", + "description": "a time limited GET request for a scheduled_maintenance report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "method": "get", + "path": "/scheduled_maintenance_report/entities", + "query": "start_time=2014-10-10T09%3A38%3A04%2B10%3A30&end_time=2014-10-10T21%3A38%3A04%2B10%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "scheduled_maintenance_reports": [ { - "start_time": "2014-10-02T21:10:18+09:30", - "duration": 3600, - "summary": "working" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 404, - "body": { - "errors": [ - "could not find entity '1234'" - ] - } } }, { - "description": "a POST request with one scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a time limited GET request for a downtime report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "method": "get", + "path": "/downtime_report/checks/www.example.com:SSH", + "query": "start_time=2014-10-10T09%3A38%3A04%2B10%3A30&end_time=2014-10-10T21%3A38%3A04%2B10%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ + "downtime_reports": [ { - "start_time": "2014-10-02T21:10:18+09:30", - "duration": 3600, - "summary": "working" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for a status report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234,5678", + "method": "get", + "path": "/status_report/checks" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-10-02T21:10:18+09:30", - "duration": 3600, - "summary": "working" - }, + "status_reports": [ { - "start_time": "2014-10-02T23:10:18+09:30", - "duration": 3600, - "summary": "more work" } ] } - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two scheduled maintenance periods", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a time limited GET request for a scheduled_maintenance report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/scheduled_maintenances/entities/1234", + "method": "get", + "path": "/scheduled_maintenance_report/checks", + "query": "start_time=2014-10-10T09%3A38%3A04%2B10%3A30&end_time=2014-10-10T21%3A38%3A04%2B10%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "scheduled_maintenances": [ - { - "start_time": "2014-10-02T21:10:18+09:30", - "duration": 3600, - "summary": "working" - }, + "scheduled_maintenance_reports": [ { - "start_time": "2014-10-02T23:10:18+09:30", - "duration": 3600, - "summary": "more work" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", - "request": { - "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-10-02T21:10:18+09:30" - } - ] - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a time limited GET request for a unscheduled_maintenance report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/unscheduled_maintenances/entities/1234,5678", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-10-02T21:10:18+09:30" - } - ] + "method": "get", + "path": "/unscheduled_maintenance_report/entities", + "query": "start_time=2014-10-10T09%3A38%3A04%2B10%3A30&end_time=2014-10-10T21%3A38%3A04%2B10%3A30" }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for an unscheduled maintenance period", - "provider_state": "no entity exists", - "request": { - "method": "patch", - "path": "/unscheduled_maintenances/entities/1234", + "status": 200, "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - { - "op": "replace", - "path": "/unscheduled_maintenances/0/end_time", - "value": "2014-10-02T21:10:18+09:30" - } - ] - }, - "response": { - "status": 404, "body": { - "errors": [ - "could not find entity '1234'" + "unscheduled_maintenance_reports": [ + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } ] } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for a status report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-10-02T21%3A10%3A18%2B09%3A30" + "method": "get", + "path": "/status_report/checks/www.example.com:SSH,www2.example.com:PING" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "status_reports": [ + { + }, + { + } + ] + } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a GET request for a downtime report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234,5678", - "query": "start_time=2014-10-02T21%3A10%3A18%2B09%3A30" + "method": "get", + "path": "/downtime_report/checks/www.example.com:SSH,www2.example.com:PING" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "downtime_reports": [ + { + }, + { + } + ] + } } }, { - "description": "a DELETE request for a scheduled maintenance period", - "provider_state": "no entity exists", + "description": "a time limited GET request for a downtime report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "delete", - "path": "/scheduled_maintenances/entities/1234", - "query": "start_time=2014-10-02T21%3A10%3A18%2B09%3A30" + "method": "get", + "path": "/downtime_report/entities/1234,5678", + "query": "start_time=2014-10-10T09%3A38%3A04%2B10%3A30&end_time=2014-10-10T21%3A38%3A04%2B10%3A30" }, "response": { - "status": 404, + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { - "errors": [ - "could not find entity '1234'" + "downtime_reports": [ + { + }, + { + } ] } } }, { - "description": "a GET request for sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a time limited GET request for a outage report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/media/abc_sms" + "path": "/outage_report/checks/www.example.com:SSH", + "query": "start_time=2014-10-10T09%3A38%3A04%2B10%3A30&end_time=2014-10-10T21%3A38%3A04%2B10%3A30" }, "response": { "status": 200, @@ -2713,15 +2513,17 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ + "outage_reports": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, + "outages": [ + + ], "links": { - "contacts": [ - "abc" + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" ] } } @@ -2730,30 +2532,42 @@ } }, { - "description": "a GET request for sms media", - "provider_state": "no contact exists", + "description": "a GET request for a outage report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/media/abc_sms" + "path": "/outage_report/checks/www.example.com:SSH" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find contact 'abc'" + "outage_reports": [ + { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } ] } } }, { - "description": "a GET request for all media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a GET request for a unscheduled_maintenance report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/media" + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -2761,26 +2575,17 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ - { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3, - "links": { - "contacts": [ - "abc" - ] - } - }, + "unscheduled_maintenance_reports": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, + "unscheduled_maintenances": [ + + ], "links": { - "contacts": [ - "abc" + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" ] } } @@ -2789,11 +2594,12 @@ } }, { - "description": "a GET request for email and sms media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a time-limited GET request for a outage report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/media/abc_email,abc_sms" + "path": "/outage_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-10-10T09%3A38%3A05%2B10%3A30&end_time=2014-10-10T21%3A38%3A05%2B10%3A30" }, "response": { "status": 200, @@ -2801,26 +2607,30 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ + "outage_reports": [ { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3, + "outages": [ + + ], "links": { - "contacts": [ - "abc" + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" ] } }, { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5, + "outages": [ + + ], "links": { - "contacts": [ - "abc" + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" ] } } @@ -2829,258 +2639,290 @@ } }, { - "description": "a DELETE request for one medium", - "provider_state": "a contact with id 'abc' has email and sms media", - "request": { - "method": "delete", - "path": "/media/abc_email", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for two media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a GET request for a scheduled_maintenance report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "delete", - "path": "/media/abc_email,abc_sms", - "body": null + "method": "get", + "path": "/scheduled_maintenance_report/entities" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } + ] + } } }, { - "description": "a DELETE request for one medium", - "provider_state": "no contact exists", + "description": "a time limited GET request for a unscheduled_maintenance report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "delete", - "path": "/media/abc_email", - "body": null + "method": "get", + "path": "/unscheduled_maintenance_report/entities/1234", + "query": "start_time=2014-10-10T09%3A38%3A05%2B10%3A30&end_time=2014-10-10T21%3A38%3A05%2B10%3A30" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find contact 'abc'" + "unscheduled_maintenance_reports": [ + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } ] } } }, { - "description": "a POST request with one medium", - "provider_state": "a contact with id 'abc' exists", + "description": "a time limited GET request for a downtime report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/contacts/abc/media", + "method": "get", + "path": "/downtime_report/checks", + "query": "start_time=2014-10-10T09%3A38%3A05%2B10%3A30&end_time=2014-10-10T21%3A38%3A05%2B10%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ + "downtime_reports": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 } ] } - }, - "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "abc_sms" - ] } }, { - "description": "a POST request with two media", - "provider_state": "a contact with id 'abc' exists", + "description": "a GET request for a outage report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/contacts/abc/media", + "method": "get", + "path": "/outage_report/entities/1234,5678" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ + "outage_reports": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } }, { - "type": "email", - "address": "ablated@example.org", - "interval": 180, - "rollup_threshold": 3 + "outages": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } - }, - "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "abc_sms", - "abc_email" - ] } }, { - "description": "a POST request with one medium", - "provider_state": "no contact exists", + "description": "a time limited GET request for a outage report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/contacts/abc/media", + "method": "get", + "path": "/outage_report/entities", + "query": "start_time=2014-10-10T09%3A38%3A05%2B10%3A30&end_time=2014-10-10T21%3A38%3A05%2B10%3A30" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "media": [ + "outage_reports": [ { - "type": "sms", - "address": "0123456789", - "interval": 300, - "rollup_threshold": 5 + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } + } + }, + { + "description": "a GET request for a status report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/status_report/entities" }, "response": { - "status": 422, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "Contact id: 'abc' could not be loaded" + "status_reports": [ + { + } ] } } }, { - "description": "a PATCH request for email media", - "provider_state": "a contact with id 'abc' has email and sms media", + "description": "a time-limited GET request for a downtime report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "patch", - "path": "/media/abc_email", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/media/0/interval", - "value": 50 - }, - { - "op": "replace", - "path": "/media/0/rollup_threshold", - "value": 3 - } - ] + "method": "get", + "path": "/downtime_report/checks/www.example.com:SSH,www2.example.com:PING", + "query": "start_time=2014-10-10T09%3A38%3A05%2B10%3A30&end_time=2014-10-10T21%3A38%3A05%2B10%3A30" }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request for email and sms media", - "provider_state": "a contact with id 'abc' has email and sms media", - "request": { - "method": "patch", - "path": "/media/abc_email,abc_sms", + "status": 200, "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - { - "op": "replace", - "path": "/media/0/interval", - "value": 50 - }, - { - "op": "replace", - "path": "/media/0/rollup_threshold", - "value": 3 - } - ] - }, - "response": { - "status": 204, - "body": "" + "body": { + "downtime_reports": [ + { + }, + { + } + ] + } } }, { - "description": "a PATCH request for email media", - "provider_state": "no contact exists", + "description": "a time limited GET request for a unscheduled_maintenance report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "patch", - "path": "/media/abc_email", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/media/0/interval", - "value": 50 - } - ] + "method": "get", + "path": "/unscheduled_maintenance_report/entities/1234,5678", + "query": "start_time=2014-10-10T09%3A38%3A05%2B10%3A30&end_time=2014-10-10T21%3A38%3A05%2B10%3A30" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find contact 'abc'" + "unscheduled_maintenance_reports": [ + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } + } ] } } }, { - "description": "a GET request for a single contact", - "provider_state": "no contact exists", + "description": "a GET request for a outage report on all checks", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/contacts/abc" + "path": "/outage_report/checks" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find contacts 'abc'" + "outage_reports": [ + { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } ] } } }, { - "description": "a GET request for a single contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a GET request for a scheduled_maintenance report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { "method": "get", - "path": "/contacts/abc" + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING" }, "response": { "status": 200, @@ -3088,24 +2930,43 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "contacts": [ + "scheduled_maintenance_reports": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC" + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } } }, { - "description": "a GET request for all contacts", - "provider_state": "no contact exists", + "description": "a GET request for a outage report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/contacts" + "path": "/outage_report/entities/1234" }, "response": { "status": 200, @@ -3113,18 +2974,30 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "contacts": [ + "outage_reports": [ + { + "outages": [ + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } ] } } }, { - "description": "a GET request for all contacts", - "provider_state": "a contact with id 'abc' exists", + "description": "a GET request for a downtime report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/contacts" + "path": "/downtime_report/entities" }, "response": { "status": 200, @@ -3132,301 +3005,345 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "contacts": [ + "downtime_reports": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC" } ] } } }, { - "description": "a DELETE request for a single contact", - "provider_state": "a contact with id 'abc' exists", - "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", - "request": { - "method": "delete", - "path": "/contacts/abc,872", - "body": null - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a DELETE request for a single contact", - "provider_state": "no contact exists", + "description": "a time limited GET request for a scheduled_maintenance report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "delete", - "path": "/contacts/abc", - "body": null + "method": "get", + "path": "/scheduled_maintenance_report/entities/1234,5678", + "query": "start_time=2014-10-10T09%3A38%3A05%2B10%3A30&end_time=2014-10-10T21%3A38%3A05%2B10%3A30" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find contacts 'abc'" + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } + } ] } } }, { - "description": "a POST request with one contact", - "provider_state": "no contact exists", + "description": "a GET request for a unscheduled_maintenance report on two checks", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "post", - "path": "/contacts", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "contacts": [ - { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC" - } - ] - } + "method": "get", + "path": "/unscheduled_maintenance_report/checks/www.example.com:SSH,www2.example.com:PING" }, "response": { - "status": 201, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - "abc" - ] - } - }, - { - "description": "a POST request with two contacts", - "provider_state": "no contact exists", - "request": { - "method": "post", - "path": "/contacts", - "headers": { - "Content-Type": "application/vnd.api+json" - }, "body": { - "contacts": [ + "unscheduled_maintenance_reports": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } }, { - "id": "def", - "first_name": "Joan", - "last_name": "Smith", - "email": "joans@example.com" + "unscheduled_maintenances": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } } ] } + } + }, + { + "description": "a time limited GET request for a outage report on two entities", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "request": { + "method": "get", + "path": "/outage_report/entities/1234,5678", + "query": "start_time=2014-10-10T09%3A38%3A05%2B10%3A30&end_time=2014-10-10T21%3A38%3A05%2B10%3A30" }, "response": { - "status": 201, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, - "body": [ - "abc", - "def" - ] + "body": { + "outage_reports": [ + { + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + }, + { + "outages": [ + + ], + "links": { + "entity": [ + "5678" + ], + "check": [ + "www2.example.com:PING" + ] + } + } + ] + } } }, { - "description": "a POST request with one contact", - "provider_state": "a contact with id 'abc' exists", + "description": "a GET request for a outage report on all entities", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "post", - "path": "/contacts", + "method": "get", + "path": "/outage_report/entities" + }, + "response": { + "status": 200, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "contacts": [ + "outage_reports": [ { - "id": "abc", - "first_name": "Jim", - "last_name": "Smith", - "email": "jims@example.com", - "timezone": "UTC" + "outages": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } } ] } + } + }, + { + "description": "a GET request for a downtime report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", + "request": { + "method": "get", + "path": "/downtime_report/entities/1234" }, "response": { - "status": 409, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "Contacts already exist with the following IDs: abc" + "downtime_reports": [ + { + } ] } } }, { - "description": "a PATCH request to change properties for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", + "description": "a time limited GET request for a scheduled_maintenance report on a single check", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/contacts/abc,872", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] + "method": "get", + "path": "/scheduled_maintenance_report/checks/www.example.com:SSH", + "query": "start_time=2014-10-10T09%3A38%3A05%2B10%3A30&end_time=2014-10-10T21%3A38%3A05%2B10%3A30" }, "response": { - "status": 204, - "body": "" + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "scheduled_maintenance_reports": [ + { + "scheduled_maintenances": [ + + ], + "links": { + "entity": [ + "1234" + ], + "check": [ + "www.example.com:SSH" + ] + } + } + ] + } } }, { - "description": "a PATCH request to change properties for a single contact", - "provider_state": "no contact exists", + "description": "a time limited GET request for a downtime report on one entity", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "patch", - "path": "/contacts/323", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] + "method": "get", + "path": "/downtime_report/entities/1234", + "query": "start_time=2014-10-10T09%3A38%3A05%2B10%3A30&end_time=2014-10-10T21%3A38%3A05%2B10%3A30" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find contacts '323'" + "downtime_reports": [ + { + } ] } } }, { - "description": "a PATCH request to change properties for a single contact", + "description": "a POST request with one notification rule", "provider_state": "a contact with id 'abc' exists", "request": { - "method": "patch", - "path": "/contacts/abc", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/contacts/0/timezone", - "value": "UTC" - } - ] - }, - "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH request to change links for two contacts", - "provider_state": "contacts with ids 'abc' and '872' exist", - "request": { - "method": "patch", - "path": "/contacts/abc,872", + "method": "post", + "path": "/contacts/abc/notification_rules", "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json" }, - "body": [ - { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" - } - ] + "body": { + "notification_rules": [ + { + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + } + ] + } }, "response": { - "status": 204, - "body": "" - } - }, - { - "description": "a PATCH requestto change a link for a single contact", - "provider_state": "a contact with id '872' exists", - "request": { - "method": "patch", - "path": "/contacts/872", + "status": 201, "headers": { - "Content-Type": "application/json-patch+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ { - "op": "add", - "path": "/contacts/0/links/entities/-", - "value": "1234" + "json_class": "Pact::Term", + "data": { + "generate": "05983623-fcef-42da-af44-ed6990b500fa", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } } ] - }, - "response": { - "status": 204, - "body": "" } }, { - "description": "a POST request with two entities", - "provider_state": "no entity exists", + "description": "a POST request with two notification rules", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/entities", + "path": "/contacts/abc/notification_rules", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "notification_rules": [ { - "name": "example.org", - "id": "57_example" + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false }, { - "name": "example2.org", - "id": "58" + "entity_tags": null, + "entities": [ + "foo-app-02.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": true, + "critical_blackhole": false } ] } @@ -3437,46 +3354,56 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "57_example", - "58" + { + "json_class": "Pact::Term", + "data": { + "generate": "05983623-fcef-42da-af44-ed6990b500fa", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + }, + { + "json_class": "Pact::Term", + "data": { + "generate": "20f182fc-6e32-4794-9007-97366d162c51", + "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} + } + } ] } }, { - "description": "a POST request with one entity", - "provider_state": "no entity exists", + "description": "a POST request with one notification rule", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/entities", + "path": "/contacts/abc/notification_rules", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "entities": [ + "notification_rules": [ { - "name": "example.org", - "id": "57_example" + "entity_tags": [ + "database", + "physical" + ], + "entities": [ + "foo-app-01.example.com" + ], + "time_restrictions": null, + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } }, - "response": { - "status": 201, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": [ - "57_example" - ] - } - }, - { - "description": "a GET request for a single entity", - "provider_state": "no entity exists", - "request": { - "method": "get", - "path": "/entities/1234" - }, "response": { "status": 404, "headers": { @@ -3484,17 +3411,17 @@ }, "body": { "errors": [ - "could not find entities: '1234'" + "could not find contact 'abc'" ] } } }, { - "description": "a GET request for a single entity", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for all notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { "method": "get", - "path": "/entities/1234" + "path": "/notification_rules" }, "response": { "status": 200, @@ -3502,21 +3429,44 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "entities": [ + "notification_rules": [ { - "name": "www.example.com", - "id": "1234" + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false } ] } } }, { - "description": "a GET request for all entities", - "provider_state": "no entity exists", + "description": "a GET request for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { "method": "get", - "path": "/entities" + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" }, "response": { "status": 200, @@ -3524,18 +3474,44 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "entities": [ + "notification_rules": [ + { + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + } ] } } }, { - "description": "a GET request for all entities", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a GET request for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { "method": "get", - "path": "/entities" + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51" }, "response": { "status": 200, @@ -3543,31 +3519,71 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "entities": [ + "notification_rules": [ { - "name": "www.example.com", - "id": "1234" + "id": "05983623-fcef-42da-af44-ed6990b500fa", + "tags": [ + + ], + "regex_tags": [ + + ], + "entities": [ + + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": false, + "critical_blackhole": false + }, + { + "id": "20f182fc-6e32-4794-9007-97366d162c51", + "tags": [ + "physical" + ], + "regex_tags": [ + + ], + "entities": [ + "example.com" + ], + "regex_entities": [ + + ], + "time_restrictions": [ + + ], + "warning_media": [ + "email" + ], + "critical_media": [ + "sms", + "email" + ], + "warning_blackhole": true, + "critical_blackhole": true } ] } } }, { - "description": "a PATCH request for a single entity", - "provider_state": "no entity exists", + "description": "a GET request for a single notification rule", + "provider_state": "no notification rule exists", "request": { - "method": "patch", - "path": "/entities/1234", - "headers": { - "Content-Type": "application/json-patch+json" - }, - "body": [ - { - "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" - } - ] + "method": "get", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" }, "response": { "status": 404, @@ -3576,25 +3592,25 @@ }, "body": { "errors": [ - "could not find entity '1234'" + "could not find notification rules '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a PATCH request for a single entity", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a PATCH request to change properties for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { "method": "patch", - "path": "/entities/1234", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/entities/0/name", - "value": "example3.com" + "path": "/notification_rules/0/warning_blackhole", + "value": false } ] }, @@ -3604,21 +3620,21 @@ } }, { - "description": "a POST request with one test notification", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a PATCH request to change properties for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH,www2.example.com:PING", + "method": "patch", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "test_notifications": [ - { - "summary": "testing" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] }, "response": { "status": 204, @@ -3626,47 +3642,41 @@ } }, { - "description": "a POST request with one test notification", - "provider_state": "no check exists", + "description": "a PATCH request to change properties for a single notification rule", + "provider_state": "no notification rule exists", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", + "method": "patch", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "test_notifications": [ - { - "summary": "testing" - } - ] - } + "body": [ + { + "op": "replace", + "path": "/notification_rules/0/warning_blackhole", + "value": false + } + ] }, "response": { "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, "body": { "errors": [ - "could not find entity 'www.example.com'" + "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" ] } } }, { - "description": "a POST request with one test notification", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for a single notification rule", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "test_notifications": [ - { - "summary": "testing" - } - ] - } + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "body": null }, "response": { "status": 204, @@ -3674,24 +3684,12 @@ } }, { - "description": "a POST request with two test notifications", - "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", + "description": "a DELETE request for two notification rules", + "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH,www2.example.com:PING", - "headers": { - "Content-Type": "application/vnd.api+json" - }, - "body": { - "test_notifications": [ - { - "summary": "testing" - }, - { - "summary": "more tests" - } - ] - } + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", + "body": null }, "response": { "status": 204, @@ -3699,28 +3697,23 @@ } }, { - "description": "a POST request with two test notifications", - "provider_state": "a check 'www.example.com:SSH' exists", + "description": "a DELETE request for a single notification rule", + "provider_state": "no notification rule exists", "request": { - "method": "post", - "path": "/test_notifications/checks/www.example.com:SSH", + "method": "delete", + "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "body": null + }, + "response": { + "status": 404, "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "test_notifications": [ - { - "summary": "testing" - }, - { - "summary": "more tests" - } + "errors": [ + "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" ] } - }, - "response": { - "status": 204, - "body": "" } }, { @@ -3795,10 +3788,10 @@ }, { "description": "a POST request with two test notifications", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", - "path": "/test_notifications/entities/1234,5678", + "path": "/test_notifications/entities/1234", "headers": { "Content-Type": "application/vnd.api+json" }, @@ -3820,10 +3813,10 @@ }, { "description": "a POST request with two test notifications", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", - "path": "/test_notifications/entities/1234", + "path": "/test_notifications/entities/1234,5678", "headers": { "Content-Type": "application/vnd.api+json" }, @@ -3844,193 +3837,69 @@ } }, { - "description": "a GET request for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "description": "a POST request with one test notification", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" - }, - "response": { - "status": 200, + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH,www2.example.com:PING", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "notification_rules": [ + "test_notifications": [ { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "summary": "testing" } ] } - } - }, - { - "description": "a GET request for a single notification rule", - "provider_state": "no notification rule exists", - "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa" - }, - "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find notification rules '05983623-fcef-42da-af44-ed6990b500fa'" - ] - } - } - }, - { - "description": "a GET request for all notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", - "request": { - "method": "get", - "path": "/notification_rules" }, "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "notification_rules": [ - { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - } - ] - } + "status": 204, + "body": "" } }, { - "description": "a GET request for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", + "description": "a POST request with one test notification", + "provider_state": "no check exists", "request": { - "method": "get", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51" - }, - "response": { - "status": 200, + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "notification_rules": [ - { - "id": "05983623-fcef-42da-af44-ed6990b500fa", - "tags": [ - - ], - "regex_tags": [ - - ], - "entities": [ - - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - }, - { - "id": "20f182fc-6e32-4794-9007-97366d162c51", - "tags": [ - "physical" - ], - "regex_tags": [ - - ], - "entities": [ - "example.com" - ], - "regex_entities": [ - - ], - "time_restrictions": [ - - ], - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": true, - "critical_blackhole": true + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" } ] } + }, + "response": { + "status": 404, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } }, { - "description": "a DELETE request for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "description": "a POST request with one test notification", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "body": null + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + } + ] + } }, "response": { "status": 204, @@ -4038,12 +3907,24 @@ } }, { - "description": "a DELETE request for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", + "description": "a POST request with two test notifications", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { - "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", - "body": null + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + }, + { + "summary": "more tests" + } + ] + } }, "response": { "status": 204, @@ -4051,54 +3932,84 @@ } }, { - "description": "a DELETE request for a single notification rule", - "provider_state": "no notification rule exists", + "description": "a POST request with two test notifications", + "provider_state": "checks 'www.example.com:SSH' and 'www2.example.com:PING' exist", "request": { - "method": "delete", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", - "body": null + "method": "post", + "path": "/test_notifications/checks/www.example.com:SSH,www2.example.com:PING", + "headers": { + "Content-Type": "application/vnd.api+json" + }, + "body": { + "test_notifications": [ + { + "summary": "testing" + }, + { + "summary": "more tests" + } + ] + } }, "response": { - "status": 404, + "status": 204, + "body": "" + } + }, + { + "description": "a POST request with one contact", + "provider_state": "no contact exists", + "request": { + "method": "post", + "path": "/contacts", "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" + "Content-Type": "application/vnd.api+json" }, "body": { - "errors": [ - "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC" + } ] } + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": [ + "abc" + ] } }, { - "description": "a POST request with one notification rule", - "provider_state": "a contact with id 'abc' exists", + "description": "a POST request with two contacts", + "provider_state": "no contact exists", "request": { "method": "post", - "path": "/contacts/abc/notification_rules", + "path": "/contacts", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "notification_rules": [ + "contacts": [ { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC" + }, + { + "id": "def", + "first_name": "Joan", + "last_name": "Smith", + "email": "joans@example.com" } ] } @@ -4109,120 +4020,170 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - { - "json_class": "Pact::Term", - "data": { - "generate": "05983623-fcef-42da-af44-ed6990b500fa", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - } + "abc", + "def" ] } }, { - "description": "a POST request with two notification rules", + "description": "a POST request with one contact", "provider_state": "a contact with id 'abc' exists", "request": { "method": "post", - "path": "/contacts/abc/notification_rules", + "path": "/contacts", "headers": { "Content-Type": "application/vnd.api+json" }, "body": { - "notification_rules": [ + "contacts": [ { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - }, + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC" + } + ] + } + }, + "response": { + "status": 409, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "Contacts already exist with the following IDs: abc" + ] + } + } + }, + { + "description": "a GET request for all contacts", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "get", + "path": "/contacts" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "contacts": [ + { + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC" + } + ] + } + } + }, + { + "description": "a GET request for all contacts", + "provider_state": "no contact exists", + "request": { + "method": "get", + "path": "/contacts" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "contacts": [ + + ] + } + } + }, + { + "description": "a GET request for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "get", + "path": "/contacts/abc" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "contacts": [ { - "entity_tags": null, - "entities": [ - "foo-app-02.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": true, - "critical_blackhole": false + "id": "abc", + "first_name": "Jim", + "last_name": "Smith", + "email": "jims@example.com", + "timezone": "UTC" } ] } + } + }, + { + "description": "a GET request for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "get", + "path": "/contacts/abc" }, "response": { - "status": 201, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, + "body": { + "errors": [ + "could not find contacts 'abc'" + ] + } + } + }, + { + "description": "a PATCH request to change properties for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", + "request": { + "method": "patch", + "path": "/contacts/abc,872", + "headers": { + "Content-Type": "application/json-patch+json" + }, "body": [ { - "json_class": "Pact::Term", - "data": { - "generate": "05983623-fcef-42da-af44-ed6990b500fa", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } - }, - { - "json_class": "Pact::Term", - "data": { - "generate": "20f182fc-6e32-4794-9007-97366d162c51", - "matcher": {"json_class":"Regexp","o":0,"s":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"} - } + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" } ] + }, + "response": { + "status": 204, + "body": "" } }, { - "description": "a POST request with one notification rule", + "description": "a PATCH request to change properties for a single contact", "provider_state": "no contact exists", "request": { - "method": "post", - "path": "/contacts/abc/notification_rules", + "method": "patch", + "path": "/contacts/323", "headers": { - "Content-Type": "application/vnd.api+json" + "Content-Type": "application/json-patch+json" }, - "body": { - "notification_rules": [ - { - "entity_tags": [ - "database", - "physical" - ], - "entities": [ - "foo-app-01.example.com" - ], - "time_restrictions": null, - "warning_media": [ - "email" - ], - "critical_media": [ - "sms", - "email" - ], - "warning_blackhole": false, - "critical_blackhole": false - } - ] - } + "body": [ + { + "op": "replace", + "path": "/contacts/0/timezone", + "value": "UTC" + } + ] }, "response": { "status": 404, @@ -4231,25 +4192,25 @@ }, "body": { "errors": [ - "could not find contact 'abc'" + "could not find contacts '323'" ] } } }, { - "description": "a PATCH request to change properties for a single notification rule", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' exists", + "description": "a PATCH request to change properties for a single contact", + "provider_state": "a contact with id 'abc' exists", "request": { "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "path": "/contacts/abc", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false + "path": "/contacts/0/timezone", + "value": "UTC" } ] }, @@ -4259,19 +4220,19 @@ } }, { - "description": "a PATCH request to change properties for two notification rules", - "provider_state": "a contact 'abc' with generic notification rule '05983623-fcef-42da-af44-ed6990b500fa' and notification rule '20f182fc-6e32-4794-9007-97366d162c51' exists", + "description": "a PATCH requestto change a link for a single contact", + "provider_state": "a contact with id '872' exists", "request": { "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa,20f182fc-6e32-4794-9007-97366d162c51", + "path": "/contacts/872", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { - "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" } ] }, @@ -4281,22 +4242,61 @@ } }, { - "description": "a PATCH request to change properties for a single notification rule", - "provider_state": "no notification rule exists", + "description": "a PATCH request to change links for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", "request": { "method": "patch", - "path": "/notification_rules/05983623-fcef-42da-af44-ed6990b500fa", + "path": "/contacts/abc,872", "headers": { "Content-Type": "application/json-patch+json" }, "body": [ { - "op": "replace", - "path": "/notification_rules/0/warning_blackhole", - "value": false + "op": "add", + "path": "/contacts/0/links/entities/-", + "value": "1234" } ] }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "a contact with id 'abc' exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for two contacts", + "provider_state": "contacts with ids 'abc' and '872' exist", + "request": { + "method": "delete", + "path": "/contacts/abc,872", + "body": null + }, + "response": { + "status": 204, + "body": "" + } + }, + { + "description": "a DELETE request for a single contact", + "provider_state": "no contact exists", + "request": { + "method": "delete", + "path": "/contacts/abc", + "body": null + }, "response": { "status": 404, "headers": { @@ -4304,14 +4304,14 @@ }, "body": { "errors": [ - "could not find notification rule '05983623-fcef-42da-af44-ed6990b500fa'" + "could not find contacts 'abc'" ] } } }, { - "description": "a POST request with two checks", - "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", + "description": "a POST request with one check", + "provider_state": "an entity 'www.example.com' with id '1234' exists", "request": { "method": "post", "path": "/checks", @@ -4323,10 +4323,6 @@ { "name": "SSH", "entity_id": "1234" - }, - { - "name": "PING", - "entity_id": "5678" } ] } @@ -4337,14 +4333,13 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "www.example.com:SSH", - "www2.example.com:PING" + "www.example.com:SSH" ] } }, { - "description": "a POST request with one check", - "provider_state": "an entity 'www.example.com' with id '1234' exists", + "description": "a POST request with two checks", + "provider_state": "entities 'www.example.com', id '1234' and 'www2.example.com', id '5678' exist", "request": { "method": "post", "path": "/checks", @@ -4356,6 +4351,10 @@ { "name": "SSH", "entity_id": "1234" + }, + { + "name": "PING", + "entity_id": "5678" } ] } @@ -4366,35 +4365,36 @@ "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": [ - "www.example.com:SSH" + "www.example.com:SSH", + "www2.example.com:PING" ] } }, { - "description": "a GET request for check 'www.example.com:SSH'", + "description": "a GET request for all checks", "provider_state": "no entity exists", "request": { "method": "get", - "path": "/checks/www.example.com:SSH" + "path": "/checks" }, "response": { - "status": 404, + "status": 200, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "errors": [ - "could not find entity checks: 'www.example.com:SSH'" + "checks": [ + ] } } }, { - "description": "a GET request for check 'www.example.com:SSH'", + "description": "a GET request for all checks", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/checks/www.example.com:SSH" + "path": "/checks" }, "response": { "status": 200, @@ -4418,11 +4418,11 @@ } }, { - "description": "a GET request for all checks", + "description": "a GET request for check 'www.example.com:SSH'", "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "get", - "path": "/checks" + "path": "/checks/www.example.com:SSH" }, "response": { "status": 200, @@ -4446,27 +4446,27 @@ } }, { - "description": "a GET request for all checks", + "description": "a GET request for check 'www.example.com:SSH'", "provider_state": "no entity exists", "request": { "method": "get", - "path": "/checks" + "path": "/checks/www.example.com:SSH" }, "response": { - "status": 200, + "status": 404, "headers": { "Content-Type": "application/vnd.api+json; charset=utf-8" }, "body": { - "checks": [ - + "errors": [ + "could not find entity checks: 'www.example.com:SSH'" ] } } }, { "description": "a PATCH request for a single check", - "provider_state": "no entity exists", + "provider_state": "a check 'www.example.com:SSH' exists", "request": { "method": "patch", "path": "/checks/www.example.com:SSH", @@ -4482,20 +4482,13 @@ ] }, "response": { - "status": 404, - "headers": { - "Content-Type": "application/vnd.api+json; charset=utf-8" - }, - "body": { - "errors": [ - "could not find entity 'www.example.com'" - ] - } + "status": 204, + "body": "" } }, { "description": "a PATCH request for a single check", - "provider_state": "a check 'www.example.com:SSH' exists", + "provider_state": "no entity exists", "request": { "method": "patch", "path": "/checks/www.example.com:SSH", @@ -4511,8 +4504,15 @@ ] }, "response": { - "status": 204, - "body": "" + "status": 404, + "headers": { + "Content-Type": "application/vnd.api+json; charset=utf-8" + }, + "body": { + "errors": [ + "could not find entity 'www.example.com'" + ] + } } } ], From 7930fd42fac12e9867a1bf5c765ead961a28e114 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Mon, 13 Oct 2014 14:18:04 +1030 Subject: [PATCH 41/69] check name speedup, aids #674 --- lib/flapjack/data/entity_check.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/flapjack/data/entity_check.rb b/lib/flapjack/data/entity_check.rb index d5beb37bf..fc8db0fd4 100755 --- a/lib/flapjack/data/entity_check.rb +++ b/lib/flapjack/data/entity_check.rb @@ -95,7 +95,7 @@ def self.for_entity(entity, check, options = {}) def self.all(options = {}) raise "Redis connection not set" unless redis = options[:redis] - checks = redis.keys('check:*').map {|c| c.match(/^check:(.+)$/) ; $1} | + checks = redis.keys('check:*').map {|c| c.sub(/^check:/, '') } | find_current_names(:redis => redis) checks.map {|ec| self.for_event_id(ec, options) @@ -105,7 +105,8 @@ def self.all(options = {}) def self.find_all_names_for_entity_name(entity_name, options = {}) raise "Redis connection not set" unless redis = options[:redis] en = Regexp.escape(entity_name) - redis.keys('check:*').map {|c| c.match(/^check:#{en}:(.+)$/); $1} + redis.keys("check:#{entity_name}:*").map {|c| c.sub(/^check:#{en}:/, '') } | + self.find_current_names_for_entity_name(entity_name, :redis => redis) end def self.find_current_names_for_entity_name(entity_name, options = {}) From d9c01f00b7b6225f4c7041e525bad896b6eb905c Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Mon, 13 Oct 2014 15:33:36 +1030 Subject: [PATCH 42/69] fold entity.check_ids_for logic into method --- lib/flapjack/data/entity.rb | 16 +++++----------- lib/flapjack/data/entity_check.rb | 7 ------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/lib/flapjack/data/entity.rb b/lib/flapjack/data/entity.rb index 89be74618..47f95d5f6 100644 --- a/lib/flapjack/data/entity.rb +++ b/lib/flapjack/data/entity.rb @@ -550,10 +550,11 @@ def self.check_ids_for(entity_ids, options = {}) entity_ids.inject({}) do |memo, entity_id| entity_name = redis.hget("entity:#{entity_id}", 'name') - unless entity_name.nil? || entity_name.empty? - checks = Flapjack::Data::EntityCheck.find_all_names_for_entity_name(entity_name, :redis => redis) - memo[entity_id] = checks.collect {|check| "#{entity_name}:#{check}" } - end + next memo if entity_name.nil? || entity_name.empty? + en = Regexp.escape(entity_name) + check_names = redis.keys("check:#{entity_name}:*").map {|c| c.sub(/^check:#{en}:/, '') } | + Flapjack::Data::EntityCheck.find_current_names_for_entity_name(entity_name, :redis => redis) + memo[entity_id] = check_names.map {|cn| "#{entity_name}:#{cn}"} memo end end @@ -568,13 +569,6 @@ def check_count checks.length end - # def as_json(*args) - # { - # "id" => self.id, - # "name" => self.name, - # } - # end - def to_jsonapi(opts = {}) json_data = { "id" => self.id, diff --git a/lib/flapjack/data/entity_check.rb b/lib/flapjack/data/entity_check.rb index fc8db0fd4..31641a75f 100755 --- a/lib/flapjack/data/entity_check.rb +++ b/lib/flapjack/data/entity_check.rb @@ -102,13 +102,6 @@ def self.all(options = {}) } end - def self.find_all_names_for_entity_name(entity_name, options = {}) - raise "Redis connection not set" unless redis = options[:redis] - en = Regexp.escape(entity_name) - redis.keys("check:#{entity_name}:*").map {|c| c.sub(/^check:#{en}:/, '') } | - self.find_current_names_for_entity_name(entity_name, :redis => redis) - end - def self.find_current_names_for_entity_name(entity_name, options = {}) raise "Redis connection not set" unless redis = options[:redis] redis.zrange("current_checks:#{entity_name}", 0, -1) From 17bf6807766a1cc7c3c78450cbc03bc95b4b2027 Mon Sep 17 00:00:00 2001 From: Sarah Kowalik Date: Tue, 14 Oct 2014 18:26:21 +1100 Subject: [PATCH 43/69] Add last_change field to status_reports in the API (closes: #678) --- lib/flapjack/gateways/jsonapi/check_presenter.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/flapjack/gateways/jsonapi/check_presenter.rb b/lib/flapjack/gateways/jsonapi/check_presenter.rb index f332b1e9f..41fd36c9c 100755 --- a/lib/flapjack/gateways/jsonapi/check_presenter.rb +++ b/lib/flapjack/gateways/jsonapi/check_presenter.rb @@ -28,6 +28,7 @@ def status 'in_unscheduled_maintenance' => @entity_check.in_unscheduled_maintenance?, 'in_scheduled_maintenance' => @entity_check.in_scheduled_maintenance?, 'last_update' => @entity_check.last_update, + 'last_change' => @entity_check.last_change, 'last_problem_notification' => @entity_check.last_notification_for_state(:problem)[:timestamp], 'last_recovery_notification' => @entity_check.last_notification_for_state(:recovery)[:timestamp], 'last_acknowledgement_notification' => @entity_check.last_notification_for_state(:acknowledgement)[:timestamp]} From 1ebe0ce7df28f954e2d7f8510550a615fea474b0 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Wed, 15 Oct 2014 13:22:25 +1030 Subject: [PATCH 44/69] data structure changes to reduce usage of redis keys * --- lib/flapjack/data/entity.rb | 91 ++++++++++++++------- lib/flapjack/data/entity_check.rb | 90 ++++++++++++-------- spec/lib/flapjack/data/entity_check_spec.rb | 3 +- spec/lib/flapjack/data/entity_spec.rb | 91 ++++----------------- 4 files changed, 131 insertions(+), 144 deletions(-) diff --git a/lib/flapjack/data/entity.rb b/lib/flapjack/data/entity.rb index 47f95d5f6..7d333f7e1 100644 --- a/lib/flapjack/data/entity.rb +++ b/lib/flapjack/data/entity.rb @@ -21,19 +21,16 @@ def self.all(options = {}) current_entity_names = (options.has_key?(:enabled) && !options[:enabled].nil?) ? Flapjack::Data::Entity.current_names(:redis => redis) : nil - keys = redis.keys("entity_id:*") - return [] unless keys.any? - ids = redis.mget(keys) - keys.inject([]) {|memo, k| - k =~ /^entity_id:(.+)$/; entity_name = $1; entity_id = ids.shift + entity_names_by_id = redis.hgetall("all_entity_names_by_id") + return [] if entity_names_by_id.empty? + entity_names_by_id.inject([]) {|memo, (eid, ename)| if options[:enabled].nil? || - (options[:enabled].is_a?(TrueClass) && current_entity_names.include?(entity_name) ) || - (options[:enabled].is_a?(FalseClass) && !current_entity_names.include?(entity_name)) + (options[:enabled].is_a?(TrueClass) && current_entity_names.include?(ename) ) || + (options[:enabled].is_a?(FalseClass) && !current_entity_names.include?(ename)) - memo << self.new(:name => entity_name, :id => entity_id, :redis => redis) + memo << self.new(:name => ename, :id => eid, :redis => redis) end - memo }.sort_by(&:name) end @@ -59,6 +56,7 @@ def self.rename(existing_name, entity_name, options = {}) alerting_check_keys = redis.keys("contact_alerting_checks:*") + all_checks = {} failed_checks = {} hashes_to_remove = [] hashes_to_add = {} @@ -77,6 +75,9 @@ def self.rename(existing_name, entity_name, options = {}) existing_check = "#{existing_name}:#{ch}" new_check = "#{entity_name}:#{ch}" + ch_all_score = redis.zscore("all_checks", existing_check) + all_checks[ch] = ch_all_score unless ch_all_score.nil? + ch_fail_score = redis.zscore("failed_checks", existing_check) failed_checks[ch] = ch_fail_score unless ch_fail_score.nil? @@ -111,12 +112,18 @@ def self.rename(existing_name, entity_name, options = {}) redis.rename(chk, chk.sub(/^#{Regexp.escape(existing_name)}:/, "#{entity_name}:")) end + all_checks.each_pair do |ch, score| + redis.zrem('all_checks', "#{existing_name}:#{ch}") + redis.zadd('all_checks', score, "#{entity_name}:#{ch}") + end + # currently failing checks failed_checks.each_pair do |ch, score| redis.zrem('failed_checks', "#{existing_name}:#{ch}") redis.zadd('failed_checks', score, "#{entity_name}:#{ch}") end + redis.rename("all_checks:#{existing_name}", "all_checks:#{entity_name}") redis.rename("current_checks:#{existing_name}", "current_checks:#{entity_name}") unless current_score.nil? @@ -160,6 +167,9 @@ def self.merge(old_name, current_name, options = {}) keys_to_delete = [] keys_to_rename = {} + all_checks_to_remove = [] + all_checks_to_add = {} + failed_checks_to_remove = [] failed_checks_to_add = {} @@ -182,6 +192,7 @@ def self.merge(old_name, current_name, options = {}) old_states = "#{old_check}:states" new_states = "#{current_check}:states" + all_checks_to_remove << old_check failed_checks_to_remove << old_check if redis.exists("check:#{current_check}") @@ -195,6 +206,9 @@ def self.merge(old_name, current_name, options = {}) keys_to_delete << old_states else + ch_all_score = redis.zscore("all_checks", old_check) + all_checks_to_add[current_check] = ch_all_score unless ch_all_score.nil? + # can move a failing checks entry over, if it exists ch_fail_score = redis.zscore("failed_checks", old_check) failed_checks_to_add[current_check] = ch_fail_score unless ch_fail_score.nil? @@ -240,6 +254,14 @@ def self.merge(old_name, current_name, options = {}) end + # TODO all_checks sorted set -- merge/rename entries + + if redis.exists("all_checks:#{current_name}") + keys_to_delete << "all_checks:#{old_name}" + else + keys_to_rename["all_checks:#{old_name}"] = "all_checks:#{current_name}" + end + if redis.exists("current_checks:#{current_name}") keys_to_delete << "current_checks:#{old_name}" else @@ -339,6 +361,14 @@ def self.merge(old_name, current_name, options = {}) redis.zunionstore(dest, [ctk, dest], :aggregate => :max) end + all_checks_to_remove.each do |actr| + redis.zrem('all_checks', actr) + end + + all_checks_to_add.each_pair do |acta, score| + redis.zadd('all_checks', score, acta) + end + failed_checks_to_remove.each do |fctr| redis.zrem('failed_checks', fctr) end @@ -415,31 +445,36 @@ def self.add(entity, options = {}) # if an entity exists with the same name as the incoming data, # use its id; failing that allocate a random one - entity_id = redis.get("entity_id:#{entity_name}") + entity_id = redis.hget('all_entity_ids_by_name', entity_name) if entity_id.nil? || entity_id.empty? entity_id = SecureRandom.uuid - redis.set("entity_id:#{entity_name}", entity_id) + redis.hset('all_entity_ids_by_name', entity_name, entity_id) + redis.hset('all_entity_names_by_id', entity_id, entity_name) redis.hset("entity:#{entity_id}", 'name', entity_name) end else # most likely from API import - existing_name = redis.hget("entity:#{entity_id}", 'name') + existing_name = redis.hget('all_entity_names_by_id', entity_id) - if existing_name.nil? + # if there's an entity with a matching name, this will change its + # id; if no entity exists it creates a new one - # if there's an entity with a matching name, this will change its - # id; if no entity exists it creates a new one - redis.set("entity_id:#{entity_name}", entity_id) + if existing_name.nil? + redis.hset('all_entity_ids_by_name', entity_name, entity_id) + redis.hset('all_entity_names_by_id', entity_id, entity_name) redis.hset("entity:#{entity_id}", 'name', entity_name) elsif existing_name != entity_name - if redis.renamenx("entity_id:#{existing_name}", "entity_id:#{entity_name}") + if redis.hexists('all_entity_ids_by_name', entity_name) + merge(existing_name, entity_name, :redis => redis) + else rename(existing_name, entity_name, :redis => redis) { + redis.hdel('all_entity_ids_by_name', existing_name) + redis.hset('all_entity_ids_by_name', entity_name, entity_id) + redis.hset('all_entity_names_by_id', entity_id, entity_name) redis.hset("entity:#{entity_id}", 'name', entity_name) } - else - merge(existing_name, entity_name, :redis => redis) end end end @@ -463,7 +498,7 @@ def self.add(entity, options = {}) def self.find_by_name(entity_name, options = {}) raise "Redis connection not set" unless redis = options[:redis] - entity_id = redis.get("entity_id:#{entity_name}") + entity_id = redis.hget("all_entity_ids_by_name", entity_name) if entity_id.nil? || entity_id.empty? # key doesn't exist return unless options[:create] @@ -476,7 +511,7 @@ def self.find_by_name(entity_name, options = {}) def self.find_by_id(entity_id, options = {}) raise "Redis connection not set" unless redis = options[:redis] - entity_name = redis.hget("entity:#{entity_id}", 'name') + entity_name = redis.hget("all_entity_names_by_id", entity_id) return if entity_name.nil? || entity_name.empty? self.new(:name => entity_name, :id => entity_id, :redis => redis) end @@ -495,21 +530,17 @@ def self.find_by_ids(entity_ids, options = {}) # time def self.find_all_name_matching(pattern, options = {}) raise "Redis connection not set" unless redis = options[:redis] + regexp = nil begin - regex = /#{pattern}/ + regexp = Regexp.new(pattern) rescue => e if @logger @logger.info("Jabber#self.find_all_name_matching - unable to use /#{pattern}/ as a regex pattern: #{e}") end - return nil + regexp = nil end - redis.keys('entity_id:*').inject([]) {|memo, check| - a, entity_name = check.split(':', 2) - if (entity_name =~ regex) && !memo.include?(entity_name) - memo << entity_name - end - memo - }.sort + return if regexp.nil? + redis.hkeys('all_entity_ids_by_name').select {|en| regexp === en }.sort end def self.current_names(options = {}) diff --git a/lib/flapjack/data/entity_check.rb b/lib/flapjack/data/entity_check.rb index 31641a75f..e3e3fd02f 100755 --- a/lib/flapjack/data/entity_check.rb +++ b/lib/flapjack/data/entity_check.rb @@ -47,10 +47,12 @@ def self.add(check_data, options = {}) logger = options[:logger] timestamp = Time.now.to_i - redis.zadd("current_checks:#{ent.name}", timestamp, check_name) - redis.zadd('current_entities', timestamp, ent.name) + entity_name = ent.name - c = self.new(ent, check_name, :logger => logger, + redis.zadd("current_checks:#{entity_name}", timestamp, check_name) + redis.zadd('current_entities', timestamp, entity_name) + + c = self.new(ent, check_name, :logger => logger, :timestamp => timestamp, :redis => redis) if check_data['tags'] && check_data['tags'].respond_to?(:each) c.add_tags(*check_data['tags']) @@ -95,11 +97,9 @@ def self.for_entity(entity, check, options = {}) def self.all(options = {}) raise "Redis connection not set" unless redis = options[:redis] - checks = redis.keys('check:*').map {|c| c.sub(/^check:/, '') } | - find_current_names(:redis => redis) - checks.map {|ec| - self.for_event_id(ec, options) - } + redis.zrange("all_checks", 0, -1).collect do |cname| + self.for_event_id(cname, options) + end end def self.find_current_names_for_entity_name(entity_name, options = {}) @@ -176,36 +176,42 @@ def self.conflate_to_keys(entity_checks_hash) def self.find_maintenance(options = {}) raise "Redis connection not set" unless redis = options[:redis] type = options[:type] - keys = redis.keys("*:#{type}_maintenances") - keys.flat_map { |k| - entity = k.split(':')[0] - check = k.split(':')[1] + + checks_with_maints = redis.zrange("all_checks", 0, -1).select do |ec_name| + # not ideal, but redis internals should essentially make this a lot + # of separate hash lookups + redis.exists("#{ec_name}:#{type}_maintenances") + end + + return [] if checks_with_maints.empty? + + entity_re = options[:entity].nil? ? nil : Regexp.new(options[:entity]) + check_re = options[:check].nil? ? nil : Regexp.new(options[:check]) + reason_re = options[:reason].nil? ? nil : Regexp.new(options[:reason]) + + checks_with_maints.inject([]) do |memo, k| + entity, check = k.split(':', 2) ec = Flapjack::Data::EntityCheck.for_entity_name(entity, check, :redis => redis) # Only return entries which match what was passed in - case - when options[:state] && options[:state] != ec.state - nil - when options[:entity] && !Regexp.new(options[:entity]).match(entity) - nil - when options[:check] && !Regexp.new(options[:check]).match(check) - nil - else - windows = ec.maintenances(nil, nil, type.to_sym => true) - windows.map { |window| - entry = { :entity => entity, - :check => check, - :state => ec.state - } - if (options[:reason].nil? || Regexp.new(options[:reason]).match(window[:summary])) && - check_maintenance_timestamp(options[:started], window[:start_time]) && - check_maintenance_timestamp(options[:finishing], window[:end_time]) && - check_maintenance_interval(options[:duration], window[:duration]) - entry.merge!(window) - end - }.compact + next memo if (options[:state] && (options[:state] != ec.state)) || + !(entity_re.nil? || entity_re.match(entity)) || + !(check_re.nil? || check_re.match(check)) + + ec.maintenances(nil, nil, type.to_sym => true).each do |window| + next unless (reason_re.nil? || reason_re.match(window[:summary])) && + check_maintenance_timestamp(options[:started], window[:start_time]) && + check_maintenance_timestamp(options[:finishing], window[:end_time]) && + check_maintenance_interval(options[:duration], window[:duration]) + + memo << { :entity => entity, + :check => check, + :state => ec.state + }.merge(window) end - }.compact + + memo + end end def self.delete_maintenance(options = {}) @@ -660,6 +666,8 @@ def update_state(new_state, options = {}) def last_update=(timestamp) @redis.hset("check:#{@key}", 'last_update', timestamp) + @redis.zadd("all_checks", timestamp, @key) + @redis.zadd("all_checks:#{entity.name}", timestamp, check) @redis.zadd("current_checks:#{entity.name}", timestamp, check) @redis.zadd('current_entities', timestamp, entity.name) end @@ -672,8 +680,11 @@ def last_update # disables a check (removes currency) def disable! + timestamp = Time.now.to_i @logger.debug("disabling check [#{@key}]") if @logger entity_name = entity.name + @redis.zadd("all_checks", timestamp, @key) + @redis.zadd("all_checks:#{entity_name}", timestamp, check) @redis.zrem("current_checks:#{entity_name}", check) if @redis.zcount("current_checks:#{entity_name}", '-inf', '+inf') == 0 @redis.zrem("current_checks:#{entity_name}", check) @@ -684,8 +695,10 @@ def disable! def enable! timestamp = Time.now.to_i entity_name = entity.name - redis.zadd("current_checks:#{entity_name}", timestamp, check) - redis.zadd('current_entities', timestamp, entity_name) + @redis.zadd("all_checks", timestamp, @key) + @redis.zadd("all_checks:#{entity_name}", timestamp, check) + @redis.zadd("current_checks:#{entity_name}", timestamp, check) + @redis.zadd('current_entities', timestamp, entity_name) end def enabled? @@ -986,6 +999,11 @@ def initialize(entity, check, options = {}) raise "Invalid entity" unless @entity = entity raise "Invalid check" unless @check = check @key = "#{entity.name}:#{check}" + if @redis.zscore("all_checks", @key).nil? + timestamp = options[:timestamp] || Time.now.to_i + @redis.zadd("all_checks", timestamp, @key) + @redis.zadd("all_checks:#{entity.name}", timestamp, check) + end @logger = options[:logger] end diff --git a/spec/lib/flapjack/data/entity_check_spec.rb b/spec/lib/flapjack/data/entity_check_spec.rb index be484808a..0344806c3 100644 --- a/spec/lib/flapjack/data/entity_check_spec.rb +++ b/spec/lib/flapjack/data/entity_check_spec.rb @@ -540,7 +540,8 @@ ec.create_scheduled_maintenance(three_hours_ago + five_minutes, seven_hours, :summary => "Scheduled maintenance started 3 hours ago") ec.create_scheduled_maintenance(four_hours_ago, seven_hours, :summary => "Scheduled maintenance started 4 hours ago") - smp = Flapjack::Data::EntityCheck.find_maintenance(:redis => @redis, :type => 'scheduled', :started => input).sort_by { |k| k[:entity] } + smp = Flapjack::Data::EntityCheck.find_maintenance(:redis => @redis, + :type => 'scheduled', :started => input).sort_by { |k| k[:entity] } expect(smp).to be_an(Array) expect(smp.size).to eq(2) diff --git a/spec/lib/flapjack/data/entity_spec.rb b/spec/lib/flapjack/data/entity_spec.rb index 45269c321..145e0caee 100644 --- a/spec/lib/flapjack/data/entity_spec.rb +++ b/spec/lib/flapjack/data/entity_spec.rb @@ -11,7 +11,7 @@ expect(entity).not_to be_nil expect(entity.name).to eq(name) - expect(@redis.get("entity_id:#{name}")).to match(/^\S+$/) + expect(@redis.hget('all_entity_ids_by_name', name)).to match(/^\S+$/) end it 'creates tags if passed when added' do @@ -193,75 +193,6 @@ end - # # Not used anywhere - # it "finds entities by tag" do - # entity0 = Flapjack::Data::Entity.add({'id' => '5000', - # 'name' => 'abc-123', - # 'contacts' => []}, - # :redis => @redis) - - # entity1 = Flapjack::Data::Entity.add({'id' => '5001', - # 'name' => 'def-456', - # 'contacts' => []}, - # :redis => @redis) - - # entity0.add_tags('source:foobar', 'abc') - # entity1.add_tags('source:foobar', 'def') - - # expect(entity0).not_to be_nil - # expect(entity0).to be_an(Flapjack::Data::Entity) - # expect(entity0.tags).to include("source:foobar") - # expect(entity0.tags).to include("abc") - # expect(entity0.tags).not_to include("def") - # expect(entity1).not_to be_nil - # expect(entity1).to be_an(Flapjack::Data::Entity) - # expect(entity1.tags).to include("source:foobar") - # expect(entity1.tags).to include("def") - # expect(entity1.tags).not_to include("abc") - - # entities = Flapjack::Data::Entity.find_all_with_tags(['abc'], :redis => @redis) - # expect(entities).to be_an(Array) - # expect(entities.size).to eq(1) - # expect(entities.first).to eq('abc-123') - - # entities = Flapjack::Data::Entity.find_all_with_tags(['donkey'], :redis => @redis) - # expect(entities).to be_an(Array) - # expect(entities).to be_empty - # end - - # it "finds entities with several tags" do - # entity0 = Flapjack::Data::Entity.add({'id' => '5000', - # 'name' => 'abc-123', - # 'contacts' => []}, - # :redis => @redis) - - # entity1 = Flapjack::Data::Entity.add({'id' => '5001', - # 'name' => 'def-456', - # 'contacts' => []}, - # :redis => @redis) - - # entity0.add_tags('source:foobar', 'abc') - # entity1.add_tags('source:foobar', 'def') - - # expect(entity0).not_to be_nil - # expect(entity0).to be_an(Flapjack::Data::Entity) - # expect(entity0.tags).to include("source:foobar") - # expect(entity0.tags).to include("abc") - # expect(entity1).not_to be_nil - # expect(entity1).to be_an(Flapjack::Data::Entity) - # expect(entity1.tags).to include("source:foobar") - # expect(entity1.tags).to include("def") - - # entities = Flapjack::Data::Entity.find_all_with_tags(['source:foobar'], :redis => @redis) - # expect(entities).to be_an(Array) - # expect(entities.size).to eq(2) - - # entities = Flapjack::Data::Entity.find_all_with_tags(['source:foobar', 'def'], :redis => @redis) - # expect(entities).to be_an(Array) - # expect(entities.size).to eq(1) - # expect(entities.first).to eq('def-456') - # end - context 'renaming and merging' do let(:time_i) { Time.now.to_i } @@ -305,13 +236,15 @@ def add_name2 end it 'renames the "entity name to id lookup" and the name in the "entity hash by id"' do - expect(@redis.get('entity_id:name1')).to eq('5000') + expect(@redis.hget('all_entity_ids_by_name', 'name1')).to eq('5000') + expect(@redis.hget('all_entity_names_by_id', '5000')).to eq('name1') expect(@redis.hget('entity:5000', 'name')).to eq('name1') add_name2 - expect(@redis.get('entity_id:name1')).to be_nil - expect(@redis.get('entity_id:name2')).to eq('5000') + expect(@redis.hget('all_entity_ids_by_name', 'name1')).to be_nil + expect(@redis.hget('all_entity_ids_by_name', 'name2')).to eq('5000') + expect(@redis.hget('all_entity_names_by_id', '5000')).to eq('name2') expect(@redis.hget('entity:5000', 'name')).to eq('name2') end @@ -321,17 +254,21 @@ def add_name2 'contacts' => []}, :redis => @redis) - expect(@redis.get('entity_id:name1')).to eq('5000') + expect(@redis.hget('all_entity_ids_by_name', 'name1')).to eq('5000') + expect(@redis.hget('all_entity_names_by_id', '5000')).to eq('name1') expect(@redis.hget('entity:5000', 'name')).to eq('name1') - expect(@redis.get('entity_id:name2')).to eq('5001') + expect(@redis.hget('all_entity_ids_by_name', 'name2')).to eq('5001') + expect(@redis.hget('all_entity_names_by_id', '5001')).to eq('name2') expect(@redis.hget('entity:5001', 'name')).to eq('name2') add_name2 # no change - expect(@redis.get('entity_id:name1')).to eq('5000') + expect(@redis.hget('all_entity_ids_by_name', 'name1')).to eq('5000') + expect(@redis.hget('all_entity_names_by_id', '5000')).to eq('name1') expect(@redis.hget('entity:5000', 'name')).to eq('name1') - expect(@redis.get('entity_id:name2')).to eq('5001') + expect(@redis.hget('all_entity_ids_by_name', 'name2')).to eq('5001') + expect(@redis.hget('all_entity_names_by_id', '5001')).to eq('name2') expect(@redis.hget('entity:5001', 'name')).to eq('name2') end From b88fba2f57c2fb9450e787e6bd1b423eced92914 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Wed, 15 Oct 2014 16:01:02 +1030 Subject: [PATCH 45/69] a bit more key blippage, migration on redis init if needed --- lib/flapjack/cli/import.rb | 6 +++- lib/flapjack/cli/maintenance.rb | 12 ++++---- lib/flapjack/cli/purge.rb | 7 ++++- lib/flapjack/cli/receiver.rb | 8 ++++- lib/flapjack/cli/simulate.rb | 9 +++--- lib/flapjack/data/entity.rb | 5 +--- lib/flapjack/data/migration.rb | 43 +++++++++++++++++++++++++++ lib/flapjack/redis_pool.rb | 6 +++- spec/lib/flapjack/data/entity_spec.rb | 6 ---- spec/lib/flapjack/redis_pool_spec.rb | 1 + tasks/entities.rake | 9 ++++-- 11 files changed, 86 insertions(+), 26 deletions(-) create mode 100644 lib/flapjack/data/migration.rb diff --git a/lib/flapjack/cli/import.rb b/lib/flapjack/cli/import.rb index d1595ac5c..5262cf9f9 100644 --- a/lib/flapjack/cli/import.rb +++ b/lib/flapjack/cli/import.rb @@ -5,6 +5,7 @@ require 'flapjack/configuration' require 'flapjack/data/contact' require 'flapjack/data/entity' +require 'flapjack/data/migration' module Flapjack module CLI @@ -61,7 +62,10 @@ def entities private def redis - @redis ||= Redis.new(@redis_options.merge(:driver => :ruby)) + return @redis unless @redis.nil? + @redis = Redis.new(@redis_options.merge(:driver => :hiredis)) + Flapjack::Data::Migration.migrate_entity_check_data_if_required(:redis => @redis) + @redis end end diff --git a/lib/flapjack/cli/maintenance.rb b/lib/flapjack/cli/maintenance.rb index 089b47ef9..fcaecbbc3 100644 --- a/lib/flapjack/cli/maintenance.rb +++ b/lib/flapjack/cli/maintenance.rb @@ -1,13 +1,12 @@ #!/usr/bin/env ruby -require 'eventmachine' -require 'em-synchrony' require 'redis' -require 'redis/connection/synchrony' +require 'hiredis' require 'flapjack/configuration' require 'flapjack/data/event' require 'flapjack/data/entity_check' +require 'flapjack/data/migration' require 'terminal-table' module Flapjack @@ -26,7 +25,7 @@ def initialize(global_options, options) exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'" end - @redis_options = config.for_redis.merge(:driver => :ruby) + @redis_options = config.for_redis @options[:redis] = redis end @@ -67,7 +66,10 @@ def create private def redis - @redis ||= Redis.new(@redis_options) + return @redis unless @redis.nil? + @redis = Redis.new(@redis_options.merge(:driver => :hiredis)) + Flapjack::Data::Migration.migrate_entity_check_data_if_required(:redis => @redis) + @redis end end diff --git a/lib/flapjack/cli/purge.rb b/lib/flapjack/cli/purge.rb index b09a11943..5d42a2566 100644 --- a/lib/flapjack/cli/purge.rb +++ b/lib/flapjack/cli/purge.rb @@ -3,6 +3,8 @@ require 'hiredis' require 'flapjack/configuration' +require 'flapjack/data/migration' + module Flapjack module CLI class Purge @@ -50,7 +52,10 @@ def check_history private def redis - @redis ||= Redis.new(@redis_options.merge(:driver => :ruby)) + return @redis unless @redis.nil? + @redis = Redis.new(@redis_options.merge(:driver => :hiredis)) + Flapjack::Data::Migration.migrate_entity_check_data_if_required(:redis => @redis) + @redis end end diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index cb8776417..172b4de2f 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -6,6 +6,7 @@ require 'flapjack/configuration' require 'flapjack/data/event' +require 'flapjack/data/migration' require 'flapjack/patches' # TODO options should be overridden by similar config file options @@ -132,7 +133,10 @@ def mirror private def redis - @redis ||= Redis.new(@redis_options.merge(:driver => :hiredis)) + return @redis unless @redis.nil? + @redis = Redis.new(@redis_options.merge(:driver => :hiredis)) + Flapjack::Data::Migration.migrate_entity_check_data_if_required(:redis => @redis) + @redis end def runner(type) @@ -369,6 +373,8 @@ def mirror_receive(opts) exit_now! "could not understand destination Redis config" end + Flapjack::Data::Migration.migrate_entity_check_data_if_required(:redis => dest_redis) + refresh_archive_index(source_addr, :source => source_redis, :dest => dest_redis) archives = mirror_get_archive_keys_stats(source_addr, :source => source_redis, :dest => dest_redis) diff --git a/lib/flapjack/cli/simulate.rb b/lib/flapjack/cli/simulate.rb index 3a3d4d694..96bf97ca8 100644 --- a/lib/flapjack/cli/simulate.rb +++ b/lib/flapjack/cli/simulate.rb @@ -1,12 +1,10 @@ #!/usr/bin/env ruby -require 'eventmachine' -require 'em-synchrony' require 'redis' -require 'redis/connection/synchrony' require 'flapjack/configuration' require 'flapjack/data/event' +require 'flapjack/data/migration' module Flapjack module CLI @@ -51,7 +49,10 @@ def ok private def redis - @redis ||= Redis.new(@redis_options) + return @redis unless @redis.nil? + @redis = Redis.new(@redis_options.merge(:driver => :hiredis)) + Flapjack::Data::Migration.migrate_entity_check_data_if_required(:redis => @redis) + @redis end def events(opts = {}) diff --git a/lib/flapjack/data/entity.rb b/lib/flapjack/data/entity.rb index 7d333f7e1..eb6fc96ad 100644 --- a/lib/flapjack/data/entity.rb +++ b/lib/flapjack/data/entity.rb @@ -451,7 +451,6 @@ def self.add(entity, options = {}) entity_id = SecureRandom.uuid redis.hset('all_entity_ids_by_name', entity_name, entity_id) redis.hset('all_entity_names_by_id', entity_id, entity_name) - redis.hset("entity:#{entity_id}", 'name', entity_name) end else # most likely from API import @@ -463,7 +462,6 @@ def self.add(entity, options = {}) if existing_name.nil? redis.hset('all_entity_ids_by_name', entity_name, entity_id) redis.hset('all_entity_names_by_id', entity_id, entity_name) - redis.hset("entity:#{entity_id}", 'name', entity_name) elsif existing_name != entity_name if redis.hexists('all_entity_ids_by_name', entity_name) @@ -473,7 +471,6 @@ def self.add(entity, options = {}) redis.hdel('all_entity_ids_by_name', existing_name) redis.hset('all_entity_ids_by_name', entity_name, entity_id) redis.hset('all_entity_names_by_id', entity_id, entity_name) - redis.hset("entity:#{entity_id}", 'name', entity_name) } end end @@ -580,7 +577,7 @@ def self.check_ids_for(entity_ids, options = {}) raise "Redis connection not set" unless redis = options[:redis] entity_ids.inject({}) do |memo, entity_id| - entity_name = redis.hget("entity:#{entity_id}", 'name') + entity_name = redis.hget('entity_names_by_id', entity_id) next memo if entity_name.nil? || entity_name.empty? en = Regexp.escape(entity_name) check_names = redis.keys("check:#{entity_name}:*").map {|c| c.sub(/^check:#{en}:/, '') } | diff --git a/lib/flapjack/data/migration.rb b/lib/flapjack/data/migration.rb new file mode 100644 index 000000000..c1b24f369 --- /dev/null +++ b/lib/flapjack/data/migration.rb @@ -0,0 +1,43 @@ +#!/usr/bin/env ruby + +module Flapjack + module Data + class Migration + + def self.migrate_entity_check_data_if_required(options = {}) + raise "Redis connection not set" unless redis = options[:redis] + return if redis.exists('all_checks') + + check_names = redis.keys('check:*').map {|c| c.sub(/^check:/, '') } | + Flapjack::Data::EntityCheck.find_current_names(:redis => redis) + + unless check_names.empty? + timestamp = Time.now.to_i + + check_names.each do |ecn| + @redis.zadd("all_checks", timestamp, ecn) + entity_name, check = cn.split(':', 2) + @redis.zadd("all_checks:#{entity_name}", timestamp, check) + # not deleting the check hashes, they store useful data + end + end + + entity_name_keys = redis.keys("entity_id:*") + unless entity_name_keys.empty? + ids = redis.mget(*entity_name_keys) + + entity_name_keys.each do |enk| + enk =~ /^entity_id:(.+)$/; entity_name = $1; entity_id = ids.shift + + redis.hset('all_entity_names_by_id', entity_id, entity_name) + redis.hset('all_entity_ids_by_name', entity_name, entity_id) + + redis.del(enk) + redis.del("entity:#{entity_id}") + end + end + end + + end + end +end \ No newline at end of file diff --git a/lib/flapjack/redis_pool.rb b/lib/flapjack/redis_pool.rb index 66b4b5342..e81153c36 100644 --- a/lib/flapjack/redis_pool.rb +++ b/lib/flapjack/redis_pool.rb @@ -10,6 +10,8 @@ require 'em-synchrony/connection_pool' +require 'flapjack/data/migration' + module Flapjack class RedisPool < EventMachine::Synchrony::ConnectionPool @@ -17,7 +19,9 @@ def initialize(opts = {}) config = opts.delete(:config) @size = opts[:size] || 5 super(:size => @size) { - ::Redis.new(config) + redis = ::Redis.new(config) + Flapjack::Data::Migration.migrate_entity_check_data_if_required(:redis => redis) + redis } end diff --git a/spec/lib/flapjack/data/entity_spec.rb b/spec/lib/flapjack/data/entity_spec.rb index 145e0caee..6d05a3e93 100644 --- a/spec/lib/flapjack/data/entity_spec.rb +++ b/spec/lib/flapjack/data/entity_spec.rb @@ -238,14 +238,12 @@ def add_name2 it 'renames the "entity name to id lookup" and the name in the "entity hash by id"' do expect(@redis.hget('all_entity_ids_by_name', 'name1')).to eq('5000') expect(@redis.hget('all_entity_names_by_id', '5000')).to eq('name1') - expect(@redis.hget('entity:5000', 'name')).to eq('name1') add_name2 expect(@redis.hget('all_entity_ids_by_name', 'name1')).to be_nil expect(@redis.hget('all_entity_ids_by_name', 'name2')).to eq('5000') expect(@redis.hget('all_entity_names_by_id', '5000')).to eq('name2') - expect(@redis.hget('entity:5000', 'name')).to eq('name2') end it 'does not rename an entity if an entity with the new name already exists' do @@ -256,20 +254,16 @@ def add_name2 expect(@redis.hget('all_entity_ids_by_name', 'name1')).to eq('5000') expect(@redis.hget('all_entity_names_by_id', '5000')).to eq('name1') - expect(@redis.hget('entity:5000', 'name')).to eq('name1') expect(@redis.hget('all_entity_ids_by_name', 'name2')).to eq('5001') expect(@redis.hget('all_entity_names_by_id', '5001')).to eq('name2') - expect(@redis.hget('entity:5001', 'name')).to eq('name2') add_name2 # no change expect(@redis.hget('all_entity_ids_by_name', 'name1')).to eq('5000') expect(@redis.hget('all_entity_names_by_id', '5000')).to eq('name1') - expect(@redis.hget('entity:5000', 'name')).to eq('name1') expect(@redis.hget('all_entity_ids_by_name', 'name2')).to eq('5001') expect(@redis.hget('all_entity_names_by_id', '5001')).to eq('name2') - expect(@redis.hget('entity:5001', 'name')).to eq('name2') end it 'renames current check state' do diff --git a/spec/lib/flapjack/redis_pool_spec.rb b/spec/lib/flapjack/redis_pool_spec.rb index 156a39501..262c05418 100644 --- a/spec/lib/flapjack/redis_pool_spec.rb +++ b/spec/lib/flapjack/redis_pool_spec.rb @@ -12,6 +12,7 @@ redis } expect(::Redis).to receive(:new).exactly(redis_count).times.and_return(*redis_conns) + expect(Flapjack::Data::Migration).to receive(:migrate_entity_check_data_if_required).exactly(redis_count).times frp = Flapjack::RedisPool.new(:size => redis_count) diff --git a/tasks/entities.rake b/tasks/entities.rake index b21b40528..b6f4201c1 100644 --- a/tasks/entities.rake +++ b/tasks/entities.rake @@ -11,7 +11,10 @@ FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'production' namespace :entities do def redis - @redis ||= Redis.new(@redis_config) + return @redis unless @redis.nil? + @redis = Redis.new(@redis_config.merge(:driver => :hiredis)) + Flapjack::Data::Migration.migrate_entity_check_data_if_required(:redis => @redis) + @redis end def orphaned_entity_names @@ -127,8 +130,8 @@ namespace :entities do if id.nil? || entity.nil? id ||= SecureRandom.uuid redis.multi - redis.set("entity_id:#{name}", id) - redis.hset("entity:#{id}", 'name', name) + redis.hset('all_entity_ids_by_name', name, id) + redis.hset('all_entity_names_by_id', id, name) redis.exec puts "Set id '#{id}' for entity #{name}'" elsif entity.name.eql?(name) From 87cb3c040c58d446eaf1ffd8418892e8b1029ec9 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Wed, 15 Oct 2014 17:09:26 +1030 Subject: [PATCH 46/69] move archive index set to mirror source, skip missing --- lib/flapjack/cli/receiver.rb | 26 +------------------------- lib/flapjack/data/event.rb | 1 + lib/flapjack/data/migration.rb | 27 +++++++++++++++++++++++++++ lib/flapjack/redis_pool.rb | 6 +++++- spec/lib/flapjack/data/event_spec.rb | 18 ++++++++++++++++++ spec/lib/flapjack/redis_pool_spec.rb | 1 + 6 files changed, 53 insertions(+), 26 deletions(-) create mode 100644 lib/flapjack/data/migration.rb diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index cb8776417..6244dbbc5 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -369,7 +369,6 @@ def mirror_receive(opts) exit_now! "could not understand destination Redis config" end - refresh_archive_index(source_addr, :source => source_redis, :dest => dest_redis) archives = mirror_get_archive_keys_stats(source_addr, :source => source_redis, :dest => dest_redis) raise "found no archives!" if archives.empty? @@ -415,15 +414,7 @@ def mirror_receive(opts) end archives = mirror_get_archive_keys_stats(source_addr, - :source => source_redis, :dest => dest_redis) - - if archives.any? {|a| a[:size] == 0} - # data may be out of date -- refresh, then reject any immediately - # expired keys directly; don't keep chasing updated data - refresh_archive_index(source_addr, :source => source_redis, :dest => dest_redis) - archives = mirror_get_archive_keys_stats(source_addr, - :source => source_redis, :dest => dest_redis).select {|a| a[:size] > 0} - end + :source => source_redis, :dest => dest_redis).select {|a| a[:size] > 0} if archives.empty? sleep 1 @@ -451,21 +442,6 @@ def mirror_get_archive_keys_stats(name, opts = {}) end end - def refresh_archive_index(name, opts = {}) - source_redis = opts[:source] - dest_redis = opts[:dest] - # refresh the key name cache, avoid repeated calls to redis KEYS - # this cache will be updated any time a new archive bucket is created - archive_keys = source_redis.keys("events_archive:*").group_by do |ak| - (source_redis.llen(ak) > 0) ? 't' : 'f' - end - - {'f' => :srem, 't' => :sadd}.each_pair do |k, cmd| - next unless archive_keys.has_key?(k) && !archive_keys[k].empty? - dest_redis.send(cmd, "known_events_archive_keys:#{name}", archive_keys[k]) - end - end - end end end diff --git a/lib/flapjack/data/event.rb b/lib/flapjack/data/event.rb index 441c960ae..feebc8bc5 100755 --- a/lib/flapjack/data/event.rb +++ b/lib/flapjack/data/event.rb @@ -88,6 +88,7 @@ def self.next(queue, opts = {}) raw = redis.rpoplpush(queue, archive_dest) return unless raw end + redis.sadd("known_events_archive_keys", archive_dest) else if options[:block] raw = redis.brpop(queue, 0)[1] diff --git a/lib/flapjack/data/migration.rb b/lib/flapjack/data/migration.rb new file mode 100644 index 000000000..94118d1c1 --- /dev/null +++ b/lib/flapjack/data/migration.rb @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby + +module Flapjack + module Data + class Migration + + def self.refresh_archive_index(options = {}) + raise "Redis connection not set" unless redis = options[:redis] + events_keys = redis.keys('events_archive:*') + if events_keys.empty? + redis.del('known_events_archive_keys') + return + end + + archive_keys = events_keys.group_by do |ak| + (redis.llen(ak) > 0) ? 't' : 'f' + end + + {'f' => :srem, 't' => :sadd}.each_pair do |k, cmd| + next unless archive_keys.has_key?(k) && !archive_keys[k].empty? + redis.send(cmd, 'known_events_archive_keys', archive_keys[k]) + end + end + + end + end +end \ No newline at end of file diff --git a/lib/flapjack/redis_pool.rb b/lib/flapjack/redis_pool.rb index 66b4b5342..1e1064fea 100644 --- a/lib/flapjack/redis_pool.rb +++ b/lib/flapjack/redis_pool.rb @@ -10,6 +10,8 @@ require 'em-synchrony/connection_pool' +require 'flapjack/data/migration' + module Flapjack class RedisPool < EventMachine::Synchrony::ConnectionPool @@ -17,7 +19,9 @@ def initialize(opts = {}) config = opts.delete(:config) @size = opts[:size] || 5 super(:size => @size) { - ::Redis.new(config) + redis = ::Redis.new(config) + Flapjack::Data::Migration.refresh_archive_index(:redis => redis) + redis } end diff --git a/spec/lib/flapjack/data/event_spec.rb b/spec/lib/flapjack/data/event_spec.rb index 743c2fc94..10e209748 100644 --- a/spec/lib/flapjack/data/event_spec.rb +++ b/spec/lib/flapjack/data/event_spec.rb @@ -27,6 +27,8 @@ it "returns the next event (blocking, archiving)" do expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(event_data.to_json) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, @@ -46,6 +48,8 @@ it "returns the next event (non-blocking, archiving)" do expect(redis).to receive(:rpoplpush). with('events', /^events_archive:/).and_return(event_data.to_json) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => false, @@ -66,6 +70,8 @@ bad_event_json = '{{{' expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) @@ -96,6 +102,8 @@ bad_event_json = bad_event_data.to_json expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) @@ -126,6 +134,8 @@ bad_event_json = bad_event_data.to_json expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) @@ -158,6 +168,8 @@ bad_event_json = bad_event_data.to_json expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) @@ -190,6 +202,8 @@ case_event_data[key] = event_data[key].upcase expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(case_event_data.to_json) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, @@ -216,6 +230,8 @@ num_event_data[key] = event_data[key].to_i.to_s expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(num_event_data.to_json) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, @@ -240,6 +256,8 @@ bad_event_json = bad_event_data.to_json expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) + expect(redis).to receive(:sadd). + with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) diff --git a/spec/lib/flapjack/redis_pool_spec.rb b/spec/lib/flapjack/redis_pool_spec.rb index 156a39501..feb5e18e5 100644 --- a/spec/lib/flapjack/redis_pool_spec.rb +++ b/spec/lib/flapjack/redis_pool_spec.rb @@ -12,6 +12,7 @@ redis } expect(::Redis).to receive(:new).exactly(redis_count).times.and_return(*redis_conns) + expect(Flapjack::Data::Migration).to receive(:refresh_archive_index).exactly(redis_count).times frp = Flapjack::RedisPool.new(:size => redis_count) From e574545f68ebae1691f42d0767eaf61f257a82c7 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Thu, 16 Oct 2014 10:57:07 +1030 Subject: [PATCH 47/69] flush events archive key list hourly, fix mirror for changes --- lib/flapjack/cli/receiver.rb | 13 ++++++------- lib/flapjack/data/event.rb | 18 +++++++++++------- lib/flapjack/data/migration.rb | 9 +++++++++ spec/lib/flapjack/data/event_spec.rb | 13 +++++++++++++ 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/lib/flapjack/cli/receiver.rb b/lib/flapjack/cli/receiver.rb index 6244dbbc5..e0deabb82 100644 --- a/lib/flapjack/cli/receiver.rb +++ b/lib/flapjack/cli/receiver.rb @@ -369,8 +369,7 @@ def mirror_receive(opts) exit_now! "could not understand destination Redis config" end - archives = mirror_get_archive_keys_stats(source_addr, :source => source_redis, - :dest => dest_redis) + archives = mirror_get_archive_keys_stats(:source => source_redis) raise "found no archives!" if archives.empty? puts "found archives: #{archives.inspect}" @@ -413,8 +412,9 @@ def mirror_receive(opts) next end - archives = mirror_get_archive_keys_stats(source_addr, - :source => source_redis, :dest => dest_redis).select {|a| a[:size] > 0} + archives = mirror_get_archive_keys_stats(:source => source_redis).select {|a| + a[:size] > 0 + } if archives.empty? sleep 1 @@ -434,10 +434,9 @@ def mirror_receive(opts) end end - def mirror_get_archive_keys_stats(name, opts = {}) + def mirror_get_archive_keys_stats(opts = {}) source_redis = opts[:source] - dest_redis = opts[:dest] - dest_redis.smembers("known_events_archive_keys:#{name}").sort.collect do |eak| + source_redis.smembers("known_events_archive_keys").sort.collect do |eak| {:name => eak, :size => source_redis.llen(eak)} end end diff --git a/lib/flapjack/data/event.rb b/lib/flapjack/data/event.rb index feebc8bc5..e51476e9e 100755 --- a/lib/flapjack/data/event.rb +++ b/lib/flapjack/data/event.rb @@ -2,6 +2,8 @@ require 'flapjack' +require 'flapjack/data/migration' + module Flapjack module Data class Event @@ -77,11 +79,15 @@ def self.next(queue, opts = {}) :events_archive_maxage => (3 * 60 * 60) } options = defaults.merge(opts) - archive_dest = nil + archive_dest = nil base_time_str = Time.now.utc.strftime("%Y%m%d%H") if options[:archive_events] archive_dest = "events_archive:#{base_time_str}" + unless @previous_base_time_str == base_time_str + Flapjack::Data::Migration.purge_expired_archive_index(:redis => redis) + end + @previous_base_time_str = base_time_str if options[:block] raw = redis.brpoplpush(queue, archive_dest, 0) else @@ -89,13 +95,11 @@ def self.next(queue, opts = {}) return unless raw end redis.sadd("known_events_archive_keys", archive_dest) + elsif options[:block] + raw = redis.brpop(queue, 0)[1] else - if options[:block] - raw = redis.brpop(queue, 0)[1] - else - raw = redis.rpop(queue) - return unless raw - end + raw = redis.rpop(queue) + return unless raw end parsed = parse_and_validate(raw, :logger => options[:logger]) if parsed.nil? diff --git a/lib/flapjack/data/migration.rb b/lib/flapjack/data/migration.rb index 94118d1c1..0e679a59d 100644 --- a/lib/flapjack/data/migration.rb +++ b/lib/flapjack/data/migration.rb @@ -22,6 +22,15 @@ def self.refresh_archive_index(options = {}) end end + def self.purge_expired_archive_index(options = {}) + raise "Redis connection not set" unless redis = options[:redis] + return unless redis.exists('known_events_archive_keys') + + redis.smembers('known_events_archive_keys').each do |ak| + redis.srem('known_events_archive_keys', ak) unless redis.exists(ak) + end + end + end end end \ No newline at end of file diff --git a/spec/lib/flapjack/data/event_spec.rb b/spec/lib/flapjack/data/event_spec.rb index 10e209748..fc9b27486 100644 --- a/spec/lib/flapjack/data/event_spec.rb +++ b/spec/lib/flapjack/data/event_spec.rb @@ -22,11 +22,16 @@ 'tags' => ['dev'] } } + before(:each) do + Flapjack::Data::Event.instance_variable_set('@previous_base_time_str', nil) + end + context 'class' do it "returns the next event (blocking, archiving)" do expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(event_data.to_json) + expect(Flapjack::Data::Migration).to receive(:purge_expired_archive_index).with(:redis => redis) expect(redis).to receive(:sadd). with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:expire) @@ -48,6 +53,7 @@ it "returns the next event (non-blocking, archiving)" do expect(redis).to receive(:rpoplpush). with('events', /^events_archive:/).and_return(event_data.to_json) + expect(Flapjack::Data::Migration).to receive(:purge_expired_archive_index).with(:redis => redis) expect(redis).to receive(:sadd). with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:expire) @@ -70,6 +76,7 @@ bad_event_json = '{{{' expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) + expect(Flapjack::Data::Migration).to receive(:purge_expired_archive_index).with(:redis => redis) expect(redis).to receive(:sadd). with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) @@ -102,6 +109,7 @@ bad_event_json = bad_event_data.to_json expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) + expect(Flapjack::Data::Migration).to receive(:purge_expired_archive_index).with(:redis => redis) expect(redis).to receive(:sadd). with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) @@ -134,6 +142,7 @@ bad_event_json = bad_event_data.to_json expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) + expect(Flapjack::Data::Migration).to receive(:purge_expired_archive_index).with(:redis => redis) expect(redis).to receive(:sadd). with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) @@ -168,6 +177,7 @@ bad_event_json = bad_event_data.to_json expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) + expect(Flapjack::Data::Migration).to receive(:purge_expired_archive_index).with(:redis => redis) expect(redis).to receive(:sadd). with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) @@ -202,6 +212,7 @@ case_event_data[key] = event_data[key].upcase expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(case_event_data.to_json) + expect(Flapjack::Data::Migration).to receive(:purge_expired_archive_index).with(:redis => redis) expect(redis).to receive(:sadd). with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:expire) @@ -230,6 +241,7 @@ num_event_data[key] = event_data[key].to_i.to_s expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(num_event_data.to_json) + expect(Flapjack::Data::Migration).to receive(:purge_expired_archive_index).with(:redis => redis) expect(redis).to receive(:sadd). with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:expire) @@ -256,6 +268,7 @@ bad_event_json = bad_event_data.to_json expect(redis).to receive(:brpoplpush). with('events', /^events_archive:/, 0).and_return(bad_event_json) + expect(Flapjack::Data::Migration).to receive(:purge_expired_archive_index).with(:redis => redis) expect(redis).to receive(:sadd). with('known_events_archive_keys', /^events_archive:/) expect(redis).to receive(:multi) From 5fbbb1fc07b4206b177726320b251667aaaa31b0 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 17 Oct 2014 09:25:34 +1030 Subject: [PATCH 48/69] more expressive variable names --- lib/flapjack/data/migration.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/flapjack/data/migration.rb b/lib/flapjack/data/migration.rb index 0e679a59d..1f5f95dbb 100644 --- a/lib/flapjack/data/migration.rb +++ b/lib/flapjack/data/migration.rb @@ -6,19 +6,19 @@ class Migration def self.refresh_archive_index(options = {}) raise "Redis connection not set" unless redis = options[:redis] - events_keys = redis.keys('events_archive:*') - if events_keys.empty? + archive_keys = redis.keys('events_archive:*') + if archive_keys.empty? redis.del('known_events_archive_keys') return end - archive_keys = events_keys.group_by do |ak| - (redis.llen(ak) > 0) ? 't' : 'f' + grouped_keys = archive_keys.group_by do |ak| + (redis.llen(ak) > 0) ? 'add' : 'remove' end - {'f' => :srem, 't' => :sadd}.each_pair do |k, cmd| - next unless archive_keys.has_key?(k) && !archive_keys[k].empty? - redis.send(cmd, 'known_events_archive_keys', archive_keys[k]) + {'remove' => :srem, 'add' => :sadd}.each_pair do |k, cmd| + next unless grouped_keys.has_key?(k) && !grouped_keys[k].empty? + redis.send(cmd, 'known_events_archive_keys', grouped_keys[k]) end end From b3ecefd1313412412ad5230e2d3f6c82bf8dac6f Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 17 Oct 2014 10:48:34 +1030 Subject: [PATCH 49/69] logging, semaphore for data migration, hat-tip to @jessereynolds --- lib/flapjack/coordinator.rb | 2 +- lib/flapjack/data/migration.rb | 57 +++++++++++++++++-- lib/flapjack/gateways/jabber.rb | 5 +- lib/flapjack/gateways/jsonapi.rb | 2 +- .../gateways/jsonapi/contact_methods.rb | 4 +- lib/flapjack/gateways/pagerduty.rb | 2 +- lib/flapjack/gateways/web.rb | 2 +- lib/flapjack/notifier.rb | 2 +- lib/flapjack/pikelet.rb | 4 +- lib/flapjack/processor.rb | 2 +- lib/flapjack/redis_pool.rb | 6 +- 11 files changed, 70 insertions(+), 18 deletions(-) diff --git a/lib/flapjack/coordinator.rb b/lib/flapjack/coordinator.rb index dca87f891..09d95f8d9 100644 --- a/lib/flapjack/coordinator.rb +++ b/lib/flapjack/coordinator.rb @@ -32,7 +32,7 @@ def start(options = {}) EM.synchrony do setup_signals if options[:signals] - redis = Flapjack::RedisPool.new(:config => @redis_options, :size => 1) + redis = Flapjack::RedisPool.new(:config => @redis_options, :size => 1, :logger => @logger) ['entity', 'check'].each do |type| discovered = redis.keys("#{type}_tag:*") redis.sadd("known_tags:#{type}_tag", discovered) unless discovered.empty? diff --git a/lib/flapjack/data/migration.rb b/lib/flapjack/data/migration.rb index 5f79d61f7..c6c8ade8f 100644 --- a/lib/flapjack/data/migration.rb +++ b/lib/flapjack/data/migration.rb @@ -1,12 +1,53 @@ #!/usr/bin/env ruby +require 'flapjack/data/semaphore' + module Flapjack module Data class Migration + ENTITY_DATA_MIGRATION = 'entity_data_migration' + + # copied from jsonapi/contact_methods.rb, could extract both into separate file + def self.obtain_semaphore(resource, options = {}) + raise "Redis connection not set" unless redis = options[:redis] + + semaphore = nil + strikes = 0 + begin + semaphore = Flapjack::Data::Semaphore.new(resource, :redis => redis, :expiry => 60) + rescue Flapjack::Data::Semaphore::ResourceLocked + strikes += 1 + if strikes < 5 + sleep 2 + retry + end + sempahore = nil + end + semaphore + end + def self.migrate_entity_check_data_if_required(options = {}) raise "Redis connection not set" unless redis = options[:redis] - return if redis.exists('all_checks') + + logger = options[:logger] + + semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, :redis => redis) + if semaphore.nil? + unless logger.nil? + logger.fatal "Could not obtain lock for data migration. Check logs " + + "for any exceptions, manually delete the '#{ENTITY_DATA_MIGRATION}' " + + "key from your Flapjack Redis database and try running Flapjack again." + end + exit + end + + if redis.exists('all_checks') + semaphore.release + return + end + + logger.warn "Upgrading Flapjack's entity/check Redis indexes..." unless logger.nil? check_names = redis.keys('check:*').map {|c| c.sub(/^check:/, '') } | Flapjack::Data::EntityCheck.find_current_names(:redis => redis) @@ -15,13 +56,15 @@ def self.migrate_entity_check_data_if_required(options = {}) timestamp = Time.now.to_i check_names.each do |ecn| - @redis.zadd("all_checks", timestamp, ecn) - entity_name, check = cn.split(':', 2) - @redis.zadd("all_checks:#{entity_name}", timestamp, check) + redis.zadd("all_checks", timestamp, ecn) + entity_name, check = ecn.split(':', 2) + redis.zadd("all_checks:#{entity_name}", timestamp, check) # not deleting the check hashes, they store useful data end end + logger.warn "Checks indexed." unless logger.nil? + entity_name_keys = redis.keys("entity_id:*") unless entity_name_keys.empty? ids = redis.mget(*entity_name_keys) @@ -36,6 +79,12 @@ def self.migrate_entity_check_data_if_required(options = {}) redis.del("entity:#{entity_id}") end end + + logger.warn "Entities indexed." unless logger.nil? + + semaphore.release + + logger.warn "Indexing complete." unless logger.nil? end def self.refresh_archive_index(options = {}) diff --git a/lib/flapjack/gateways/jabber.rb b/lib/flapjack/gateways/jabber.rb index ada930549..cf9d1255c 100644 --- a/lib/flapjack/gateways/jabber.rb +++ b/lib/flapjack/gateways/jabber.rb @@ -46,9 +46,10 @@ def initialize(opts = {}) @redis_config = opts[:redis_config] || {} @boot_time = opts[:boot_time] - @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2) - @logger = opts[:logger] + + @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2, :logger => @logger) + @logger.debug("Jabber Initializing") @buffer = [] diff --git a/lib/flapjack/gateways/jsonapi.rb b/lib/flapjack/gateways/jsonapi.rb index e4a1a9f43..5a9ff98f7 100644 --- a/lib/flapjack/gateways/jsonapi.rb +++ b/lib/flapjack/gateways/jsonapi.rb @@ -183,7 +183,7 @@ def initialize(resource) class << self def start - @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2) + @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2, :logger => @logger) @logger.info "starting jsonapi - class" diff --git a/lib/flapjack/gateways/jsonapi/contact_methods.rb b/lib/flapjack/gateways/jsonapi/contact_methods.rb index 86c326b1d..cd076ce13 100644 --- a/lib/flapjack/gateways/jsonapi/contact_methods.rb +++ b/lib/flapjack/gateways/jsonapi/contact_methods.rb @@ -25,11 +25,11 @@ def obtain_semaphore(resource) semaphore = Flapjack::Data::Semaphore.new(resource, :redis => redis, :expiry => 30) rescue Flapjack::Data::Semaphore::ResourceLocked strikes += 1 - raise Flapjack::Gateways::JSONAPI::ResourceLocked.new(resource) unless strikes < 3 + raise Flapjack::Gateways::JSONAPI::ResourceLocked.new(resource) if strikes >= 3 sleep 1 retry end - raise Flapjack::Gateways::JSONAPI::ResourceLocked.new(resource) unless semaphore + raise Flapjack::Gateways::JSONAPI::ResourceLocked.new(resource) if semaphore.nil? semaphore end diff --git a/lib/flapjack/gateways/pagerduty.rb b/lib/flapjack/gateways/pagerduty.rb index a7d2899b1..8aa45d6a2 100644 --- a/lib/flapjack/gateways/pagerduty.rb +++ b/lib/flapjack/gateways/pagerduty.rb @@ -23,7 +23,7 @@ def initialize(opts = {}) @config = opts[:config] @logger = opts[:logger] @redis_config = opts[:redis_config] || {} - @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2) + @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2, :logger => @logger) @logger.debug("New Pagerduty pikelet with the following options: #{@config.inspect}") diff --git a/lib/flapjack/gateways/web.rb b/lib/flapjack/gateways/web.rb index e6237aea2..15c4b32f0 100755 --- a/lib/flapjack/gateways/web.rb +++ b/lib/flapjack/gateways/web.rb @@ -40,7 +40,7 @@ class Web < Sinatra::Base class << self def start - @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2) + @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2, :logger => @logger) @logger.info "starting web - class" diff --git a/lib/flapjack/notifier.rb b/lib/flapjack/notifier.rb index 136820143..8038eb155 100644 --- a/lib/flapjack/notifier.rb +++ b/lib/flapjack/notifier.rb @@ -26,7 +26,7 @@ def initialize(opts = {}) @config = opts[:config] @redis_config = opts[:redis_config] || {} @logger = opts[:logger] - @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2) + @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2, :logger => @logger) @notifications_queue = @config['queue'] || 'notifications' diff --git a/lib/flapjack/pikelet.rb b/lib/flapjack/pikelet.rb index 288ae0abc..377cd0d4d 100644 --- a/lib/flapjack/pikelet.rb +++ b/lib/flapjack/pikelet.rb @@ -97,7 +97,7 @@ def stop def configure_resque unless ::Resque.instance_variable_defined?('@flapjack_pool') && !::Resque.instance_variable_get('@flapjack_pool').nil? - resque_pool = Flapjack::RedisPool.new(:config => @redis_config) + resque_pool = Flapjack::RedisPool.new(:config => @redis_config, :logger => @logger) ::Resque.instance_variable_set('@flapjack_pool', resque_pool) ::Resque.redis = resque_pool end @@ -175,7 +175,7 @@ def initialize(type, pikelet_klass, opts = {}) # guard against another Resque pikelet having created the pool already unless defined?(@@redis_connection) && !@@redis_connection.nil? - @@redis_connection = Flapjack::RedisPool.new(:config => @redis_config) + @@redis_connection = Flapjack::RedisPool.new(:config => @redis_config, :logger => @logger) end pikelet_klass.instance_variable_set('@config', @config) diff --git a/lib/flapjack/processor.rb b/lib/flapjack/processor.rb index 3bc85dc2c..a0658df8d 100755 --- a/lib/flapjack/processor.rb +++ b/lib/flapjack/processor.rb @@ -26,7 +26,7 @@ def initialize(opts = {}) @redis_config = opts[:redis_config] || {} @logger = opts[:logger] - @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2) + @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2, :logger => @logger) @queue = @config['queue'] || 'events' diff --git a/lib/flapjack/redis_pool.rb b/lib/flapjack/redis_pool.rb index 60750df9a..4cc9d095a 100644 --- a/lib/flapjack/redis_pool.rb +++ b/lib/flapjack/redis_pool.rb @@ -17,10 +17,12 @@ class RedisPool < EventMachine::Synchrony::ConnectionPool def initialize(opts = {}) config = opts.delete(:config) - @size = opts[:size] || 5 + @size = opts[:size] || 5 + logger = opts[:logger] super(:size => @size) { redis = ::Redis.new(config) - Flapjack::Data::Migration.migrate_entity_check_data_if_required(:redis => redis) + Flapjack::Data::Migration.migrate_entity_check_data_if_required(:redis => redis, + :logger => logger) Flapjack::Data::Migration.refresh_archive_index(:redis => redis) redis } From edab7da155baf3add293a7e5a2d1290bef725e7e Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Fri, 17 Oct 2014 11:48:08 +1030 Subject: [PATCH 50/69] improve error message --- lib/flapjack/data/migration.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/flapjack/data/migration.rb b/lib/flapjack/data/migration.rb index c6c8ade8f..48db8cdc9 100644 --- a/lib/flapjack/data/migration.rb +++ b/lib/flapjack/data/migration.rb @@ -35,9 +35,11 @@ def self.migrate_entity_check_data_if_required(options = {}) semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, :redis => redis) if semaphore.nil? unless logger.nil? - logger.fatal "Could not obtain lock for data migration. Check logs " + - "for any exceptions, manually delete the '#{ENTITY_DATA_MIGRATION}' " + - "key from your Flapjack Redis database and try running Flapjack again." + logger.fatal "Could not obtain lock for data migration. Ensure that " + + "no other flapjack processes are running that might be executing " + + "migrations, check logs for any exceptions, manually delete the " + + "'#{ENTITY_DATA_MIGRATION}' key from your Flapjack Redis " + + "database and try running Flapjack again." end exit end From 9cf5dcf773a41d0133d773c103acc7c4f9d6eb85 Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Fri, 17 Oct 2014 13:19:54 +1030 Subject: [PATCH 51/69] prepare 1.2.0rc2 release --- CHANGELOG.md | 6 ++++++ Gemfile-ruby1.9.lock | 2 +- Gemfile.lock | 2 +- lib/flapjack/version.rb | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f963a4b4..69e0670ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ## Flapjack Changelog +# 1.2.0rc2 - 2014-10-17 +- Feature: Cache entity and check name <-> id lookups #682 (@ali-graham) +- Chore: Add last_change field to status_reports in the API (closes: #678) #679 (@Hobbsee) +- Chore: Move archive cache responsibility to mirror source. #683 (@ali-graham) +- Bug: jsonapi: GET /entities is non performant #674 (@ali-graham) + # 1.2.0rc1 - 2014-10-08 - Feature: Allow updating an entities name via PATCH /entities/id[,id...] #628 (@ali-graham) - Feature: Pact specs for flapjack-diner compatability testing #663 (@ali-graham) diff --git a/Gemfile-ruby1.9.lock b/Gemfile-ruby1.9.lock index 0c6beb925..df43bdaab 100644 --- a/Gemfile-ruby1.9.lock +++ b/Gemfile-ruby1.9.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - flapjack (1.2.0rc1) + flapjack (1.2.0rc2) activesupport (~> 3.2.14) blather (~> 0.8.3) chronic diff --git a/Gemfile.lock b/Gemfile.lock index bc7d226e3..444a8ff0a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - flapjack (1.2.0rc1) + flapjack (1.2.0rc2) activesupport (~> 3.2.14) blather (~> 0.8.3) chronic diff --git a/lib/flapjack/version.rb b/lib/flapjack/version.rb index 027b20afc..a595c1546 100644 --- a/lib/flapjack/version.rb +++ b/lib/flapjack/version.rb @@ -1,6 +1,6 @@ #!/usr/bin/env ruby module Flapjack - VERSION = "1.2.0rc1" + VERSION = "1.2.0rc2" end From eeb5cbe4739a36db7c19de84fba8922ee6c457ec Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Tue, 21 Oct 2014 16:02:06 +1030 Subject: [PATCH 52/69] version check typo --- tasks/benchmarks.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/benchmarks.rake b/tasks/benchmarks.rake index e3ed2dd83..94edd7894 100644 --- a/tasks/benchmarks.rake +++ b/tasks/benchmarks.rake @@ -97,7 +97,7 @@ namespace :benchmarks do # - time to failure varies evenly between 1 hour and 1 month # - time to recovery varies evenly between 10 seconds and 1 week task :benchmark do - unless RUBY_VERSION.split('.')[0] == '1' && RUBY_VERSION.split('.')[1] == '8' + unless RUBY_VERSION.split('.')[0] == '1' && RUBY_VERSION.split('.')[1] == '9' # Flapjack doesn't support 1.8 or below, so just checking for 1.9 is OK raise "perftools.rb doesn't work on Ruby 2.0 or greater" end From 7eacf6da0fe5d274b077ee20eb003a8ed7f51034 Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Thu, 23 Oct 2014 15:04:42 +1030 Subject: [PATCH 53/69] add logging of inbound and outbound headers in debug mode --- lib/flapjack/gateways/jsonapi.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/flapjack/gateways/jsonapi.rb b/lib/flapjack/gateways/jsonapi.rb index 5a9ff98f7..e2b9784ee 100644 --- a/lib/flapjack/gateways/jsonapi.rb +++ b/lib/flapjack/gateways/jsonapi.rb @@ -229,7 +229,7 @@ def base_url (request.query_string.length > 0)) ? "?#{request.query_string}" : "" if logger.debug? input = env['rack.input'].read - logger.debug("#{request.request_method} #{request.path_info}#{query_string} #{input}") + logger.debug("#{request.request_method} #{request.path_info}#{query_string} Headers: #{headers.inspect}, Body: #{input}") elsif logger.info? input = env['rack.input'].read input_short = input.gsub(/\n/, '').gsub(/\s+/, ' ') @@ -250,8 +250,9 @@ def base_url else response.body.to_s end + headers_debug = response.headers.to_s logger.debug("Returning #{response.status} for #{request.request_method} " + - "#{request.path_info}#{query_string}, body: #{body_debug}") + "#{request.path_info}#{query_string}, headers: #{headers_debug}, body: #{body_debug}") elsif logger.info? logger.info("Returning #{response.status} for #{request.request_method} " + "#{request.path_info}#{query_string}") From 52448cebb84e0b3cbb795f8e80578132076f7caf Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Thu, 23 Oct 2014 17:45:28 +1030 Subject: [PATCH 54/69] fix deb repo url in dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1b73f292f..8e159e191 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ RUN apt-get install -y gnupg RUN gpg --keyserver keys.gnupg.net --recv-keys 803709B6 RUN gpg -a --export 803709B6 | apt-key add - -RUN echo "deb http://packages.flapjack.io/deb/1.0 trusty main" | tee /etc/apt/sources.list.d/flapjack.list +RUN echo "deb http://packages.flapjack.io/deb/v1 trusty main" | tee /etc/apt/sources.list.d/flapjack.list RUN apt-get update RUN apt-cache policy flapjack RUN apt-get install -y flapjack From be139d122a943493d27354264e680aa6d509560d Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Mon, 27 Oct 2014 14:28:14 +1030 Subject: [PATCH 55/69] cleanup, remove irrelevant error --- lib/flapjack/notifier.rb | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/flapjack/notifier.rb b/lib/flapjack/notifier.rb index 8038eb155..8f26ae28e 100644 --- a/lib/flapjack/notifier.rb +++ b/lib/flapjack/notifier.rb @@ -90,7 +90,8 @@ def process_notification(notification) timestamp = Time.now event_id = notification.event_id - entity_check = Flapjack::Data::EntityCheck.for_event_id(event_id, :redis => @redis, :logger => @logger) + entity_check = Flapjack::Data::EntityCheck.for_event_id(event_id, + :redis => @redis, :logger => @logger) contacts = entity_check.contacts if contacts.empty? @@ -99,14 +100,11 @@ def process_notification(notification) return end - messages = notification.messages(contacts, :default_timezone => @default_contact_timezone, - :logger => @logger) + messages = notification.messages(contacts, + :default_timezone => @default_contact_timezone, :logger => @logger) notification_contents = notification.contents - in_unscheduled_maintenance = entity_check.in_scheduled_maintenance? - in_scheduled_maintenance = entity_check.in_unscheduled_maintenance? - messages.each do |message| media_type = message.medium address = message.address @@ -123,9 +121,7 @@ def process_notification(notification) memo end contents['rollup_alerts'] = rollup_alerts - contents['rollup_threshold'] = message.contact.rollup_threshold_for_media(media_type) - end @notifylog.info("#{event_id} | " + From 88220b270ce278029ad582fbafeab6bba6f244be Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Thu, 30 Oct 2014 10:57:45 +1030 Subject: [PATCH 56/69] bugfix for reports API req with malformed check name --- lib/flapjack/data/entity_check.rb | 17 +++++++---------- lib/flapjack/gateways/jsonapi/report_methods.rb | 15 +++++++++++---- .../gateways/jsonapi/check_methods_spec.rb | 10 ++++++++++ .../gateways/jsonapi/report_methods_spec.rb | 9 +++------ 4 files changed, 31 insertions(+), 20 deletions(-) diff --git a/lib/flapjack/data/entity_check.rb b/lib/flapjack/data/entity_check.rb index e3e3fd02f..346400879 100755 --- a/lib/flapjack/data/entity_check.rb +++ b/lib/flapjack/data/entity_check.rb @@ -163,16 +163,6 @@ def self.unacknowledged_failing(options = {}) } end - def self.conflate_to_keys(entity_checks_hash) - result = [] - entity_checks_hash.each {|entity, checks| - checks.each {|check| - result << "#{entity}:#{check}" - } - } - result - end - def self.find_maintenance(options = {}) raise "Redis connection not set" unless redis = options[:redis] type = options[:type] @@ -1007,6 +997,13 @@ def initialize(entity, check, options = {}) @logger = options[:logger] end + def self.conflate_to_keys(entity_checks_hash) + entity_checks_hash.inject([]) {|memo, (entity, checks)| + memo += checks.collect {|check| "#{entity}:#{check}" } + memo + } + end + def format_perfdata(perfdata) # example perfdata: time=0.486630s;;;0.000000 size=909B;;;0 items = perfdata.split(' ') diff --git a/lib/flapjack/gateways/jsonapi/report_methods.rb b/lib/flapjack/gateways/jsonapi/report_methods.rb index 68c85a3eb..6d4ae39a6 100644 --- a/lib/flapjack/gateways/jsonapi/report_methods.rb +++ b/lib/flapjack/gateways/jsonapi/report_methods.rb @@ -27,11 +27,18 @@ def load_api_data(entity_ids, event_ids, &block) end checks = if event_ids.nil? - Flapjack::Data::EntityCheck.find_current_names(:redis => redis).collect {|check_name| - find_entity_check_by_name(*check_name.split(':', 2)) - } + Flapjack::Data::EntityCheck.find_current_names(:redis => redis). + each_with_object([]) do |check_name, memo| + en, cn = check_name.split(':', 2) + halt(500, 'Malformed check ID') if en.nil? || cn.nil? + memo << find_entity_check_by_name(en, cn) + end elsif !event_ids.empty? - event_ids.collect {|event_id| find_entity_check_by_name(*event_id.split(':', 2)) } + event_ids.each_with_object([]) do |event_id, memo| + en, cn = event_id.split(':', 2) + halt(500, 'Malformed check ID') if en.nil? || cn.nil? + memo << find_entity_check_by_name(en, cn) + end else nil end diff --git a/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb b/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb index 6b3336005..aa4429275 100644 --- a/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb +++ b/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb @@ -83,6 +83,16 @@ expect(last_response).to be_ok expect(last_response.body).to eq({:checks => [check_data, check_data_2]}.to_json) end + + it "does not find a check" do + expect(Flapjack::Data::EntityCheck).to receive(:for_event_id). + with('www.example.com:SSH', :logger => @logger, :redis => redis). + and_return(nil) + + aget '/checks/www.example.com:SSH' + expect(last_response).to be_not_found + end + it "creates checks from a submitted list" do checks = {'checks' => [ diff --git a/spec/lib/flapjack/gateways/jsonapi/report_methods_spec.rb b/spec/lib/flapjack/gateways/jsonapi/report_methods_spec.rb index 53c153b5f..67d7c98e3 100644 --- a/spec/lib/flapjack/gateways/jsonapi/report_methods_spec.rb +++ b/spec/lib/flapjack/gateways/jsonapi/report_methods_spec.rb @@ -168,12 +168,9 @@ expect(last_response).to be_not_found end - it "should not show the status for a check that's not found on an entity" do - expect(Flapjack::Data::EntityCheck).to receive(:for_entity_name). - with(entity_name, 'SSH', :redis => redis).and_return(nil) - - aget "/status_report/checks/#{entity_name}:SSH" - expect(last_response).to be_not_found + it "should not show the status for a check with a malformed name" do + aget "/status_report/checks/SSH" + expect(last_response.status).to eq(500) end it "returns a list of scheduled maintenance periods for an entity" do From faa038f7bb39a494d588cc77ee13d2106af79b1f Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Thu, 30 Oct 2014 16:29:39 +1030 Subject: [PATCH 57/69] multi blocks for safe connection pool usage, cucumber upgrade --- Gemfile | 2 +- Gemfile-ruby1.9.lock | 7 +- Gemfile.lock | 7 +- features/steps/notifications_steps.rb | 20 +- features/support/env.rb | 10 +- flapjack.gemspec | 2 +- lib/flapjack/data/entity.rb | 233 +++++++++++--------- lib/flapjack/data/entity_check.rb | 81 ++++--- lib/flapjack/data/event.rb | 8 +- lib/flapjack/processor.rb | 52 ++--- spec/lib/flapjack/data/contact_spec.rb | 7 +- spec/lib/flapjack/data/entity_check_spec.rb | 8 +- spec/lib/flapjack/data/event_spec.rb | 36 ++- tasks/entities.rake | 8 +- 14 files changed, 253 insertions(+), 228 deletions(-) diff --git a/Gemfile b/Gemfile index 3eb21c740..a529a9473 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,7 @@ end group :test do gem 'rspec', '~> 3.0' - gem 'cucumber' + gem 'cucumber', '>= 2.0.0.beta.3' gem 'delorean' gem 'rack-test' gem 'pact' diff --git a/Gemfile-ruby1.9.lock b/Gemfile-ruby1.9.lock index df43bdaab..9c8dab994 100644 --- a/Gemfile-ruby1.9.lock +++ b/Gemfile-ruby1.9.lock @@ -54,12 +54,15 @@ GEM cookiejar (0.3.2) crack (0.4.2) safe_yaml (~> 1.0.0) - cucumber (1.3.17) + cucumber (2.0.0.beta.3) builder (>= 2.1.2) + cucumber-core (~> 1.0.0.beta.3) diff-lcs (>= 1.1.3) gherkin (~> 2.12) multi_json (>= 1.7.5, < 2.0) multi_test (>= 0.1.1) + cucumber-core (1.0.0.beta.3) + gherkin (~> 2.12.0) daemons (1.1.9) dante (0.2.0) debugger-ruby_core_source (1.3.5) @@ -232,7 +235,7 @@ PLATFORMS DEPENDENCIES async_rack_test (>= 0.0.5) - cucumber + cucumber (>= 2.0.0.beta.3) debugger-ruby_core_source (>= 1.3.4) delorean flapjack! diff --git a/Gemfile.lock b/Gemfile.lock index 444a8ff0a..9b50c7d0a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -54,12 +54,15 @@ GEM cookiejar (0.3.2) crack (0.4.2) safe_yaml (~> 1.0.0) - cucumber (1.3.17) + cucumber (2.0.0.beta.3) builder (>= 2.1.2) + cucumber-core (~> 1.0.0.beta.3) diff-lcs (>= 1.1.3) gherkin (~> 2.12) multi_json (>= 1.7.5, < 2.0) multi_test (>= 0.1.1) + cucumber-core (1.0.0.beta.3) + gherkin (~> 2.12.0) daemons (1.1.9) dante (0.2.0) delorean (2.1.0) @@ -230,7 +233,7 @@ PLATFORMS DEPENDENCIES async_rack_test (>= 0.0.5) - cucumber + cucumber (>= 2.0.0.beta.3) delorean flapjack! fuubar diff --git a/features/steps/notifications_steps.rb b/features/steps/notifications_steps.rb index 55aeb0eec..f940b17ec 100644 --- a/features/steps/notifications_steps.rb +++ b/features/steps/notifications_steps.rb @@ -2,16 +2,16 @@ # copied from flapjack-populator # TODO use Flapjack::Data::Contact.add def add_contact(contact = {}) - @redis.multi - @redis.del("contact:#{contact['id']}") - @redis.del("contact_media:#{contact['id']}") - @redis.hset("contact:#{contact['id']}", 'first_name', contact['first_name']) - @redis.hset("contact:#{contact['id']}", 'last_name', contact['last_name']) - @redis.hset("contact:#{contact['id']}", 'email', contact['email']) - contact['media'].each_pair {|medium, address| - @redis.hset("contact_media:#{contact['id']}", medium, address) - } - @redis.exec + @redis.multi do |multi| + multi.del("contact:#{contact['id']}") + multi.del("contact_media:#{contact['id']}") + multi.hset("contact:#{contact['id']}", 'first_name', contact['first_name']) + multi.hset("contact:#{contact['id']}", 'last_name', contact['last_name']) + multi.hset("contact:#{contact['id']}", 'email', contact['email']) + contact['media'].each_pair {|medium, address| + multi.hset("contact_media:#{contact['id']}", medium, address) + } + end end Given /^the user wants to receive SMS notifications for entity '([\w\.\-]+)'$/ do |entity| diff --git a/features/support/env.rb b/features/support/env.rb index b60b97958..ed210d791 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -115,16 +115,13 @@ def self.time_travel_to(dest_time) config = Flapjack::Configuration.new redis_opts = config.load(FLAPJACK_CONFIG) ? - config.for_redis : + config.for_redis.merge(:driver => :ruby) : {:db => 14, :driver => :ruby} redis = ::Redis.new(redis_opts) redis.flushdb RedisDelorean.before_all(:redis => redis) redis.quit -# NB: this seems to execute outside the Before/After hooks -# regardless of placement -- this is what we want, as the -# @redis driver should be initialised in the sync block. Around do |scenario, blk| EM.synchrony do blk.call @@ -140,7 +137,6 @@ def self.time_travel_to(dest_time) @logger.messages = [] end - Before('@processor') do @processor = Flapjack::Processor.new(:logger => @logger, :redis_config => redis_opts, :config => {}) @@ -150,6 +146,7 @@ def self.time_travel_to(dest_time) After('@processor') do @redis.flushdb @redis.quit + @redis = nil end Before('@notifier') do @@ -165,6 +162,7 @@ def self.time_travel_to(dest_time) After('@notifier') do @notifier_redis.flushdb @notifier_redis.quit + @notifier_redis = nil end Before('@resque') do @@ -173,7 +171,7 @@ def self.time_travel_to(dest_time) end Before('@time') do - RedisDelorean.before_each(:redis => @redis) + RedisDelorean.before_each(:redis => @redis || @notifier_redis) end After('@time') do diff --git a/flapjack.gemspec b/flapjack.gemspec index 6e77f9dd1..43a00f76d 100644 --- a/flapjack.gemspec +++ b/flapjack.gemspec @@ -21,10 +21,10 @@ Gem::Specification.new do |gem| gem.add_dependency 'dante' gem.add_dependency 'oj', '>= 2.9.0' gem.add_dependency 'eventmachine', '~> 1.0.0' + gem.add_dependency 'redis', '~> 3.0.6' gem.add_dependency 'hiredis' gem.add_dependency 'em-synchrony', '~> 1.0.2' gem.add_dependency 'em-http-request' - gem.add_dependency 'redis', '~> 3.0.6' gem.add_dependency 'em-resque' gem.add_dependency 'resque', '~> 1.23.0' gem.add_dependency 'sinatra' diff --git a/lib/flapjack/data/entity.rb b/lib/flapjack/data/entity.rb index eb6fc96ad..9f31a6825 100644 --- a/lib/flapjack/data/entity.rb +++ b/lib/flapjack/data/entity.rb @@ -44,12 +44,17 @@ def self.rename(existing_name, entity_name, options = {}) check_history_keys = redis.keys("#{existing_name}:*:states") + redis.keys("#{existing_name}:*:state") + - redis.keys("#{existing_name}:*:summary") + redis.keys("#{existing_name}:*:sorted_state_timestamps") action_keys = redis.keys("#{existing_name}:*:actions") - maint_keys = redis.keys("#{existing_name}:*:*scheduled_maintenance*") + + maint_keys = redis.keys("#{existing_name}:*:*scheduled_maintenance*") + + all_summary_keys = redis.keys("#{existing_name}:*:summary") + maint_summary_keys = redis.keys("#{existing_name}:*:*scheduled_maintenance:summary") + check_summary_keys = all_summary_keys - maint_summary_keys + + check_history_keys += check_summary_keys notif_keys = redis.keys("#{existing_name}:*:last_*_notification") + redis.keys("#{existing_name}:*:*_notifications") @@ -100,54 +105,61 @@ def self.rename(existing_name, entity_name, options = {}) block_keys = redis.keys("drop_alerts_for_contact:*:*:#{existing_name}:*:*") - redis.multi + rename_all_checks = redis.exists("all_checks:#{existing_name}") + rename_current_checks = redis.exists("current_checks:#{existing_name}") - yield if block_given? # entity id -> name update from add() + redis.multi do |multi| - check_state_keys.each do |csk| - redis.rename(csk, csk.sub(/^check:#{Regexp.escape(existing_name)}:/, "check:#{entity_name}:")) - end + yield(multi) if block_given? # entity id -> name update from add() - (check_history_keys + action_keys + maint_keys + notif_keys).each do |chk| - redis.rename(chk, chk.sub(/^#{Regexp.escape(existing_name)}:/, "#{entity_name}:")) - end + check_state_keys.each do |csk| + multi.rename(csk, csk.sub(/^check:#{Regexp.escape(existing_name)}:/, "check:#{entity_name}:")) + end - all_checks.each_pair do |ch, score| - redis.zrem('all_checks', "#{existing_name}:#{ch}") - redis.zadd('all_checks', score, "#{entity_name}:#{ch}") - end + (check_history_keys + action_keys + maint_keys + notif_keys).each do |chk| + multi.rename(chk, chk.sub(/^#{Regexp.escape(existing_name)}:/, "#{entity_name}:")) + end - # currently failing checks - failed_checks.each_pair do |ch, score| - redis.zrem('failed_checks', "#{existing_name}:#{ch}") - redis.zadd('failed_checks', score, "#{entity_name}:#{ch}") - end + all_checks.each_pair do |ch, score| + multi.zrem('all_checks', "#{existing_name}:#{ch}") + multi.zadd('all_checks', score, "#{entity_name}:#{ch}") + end - redis.rename("all_checks:#{existing_name}", "all_checks:#{entity_name}") - redis.rename("current_checks:#{existing_name}", "current_checks:#{entity_name}") + # currently failing checks + failed_checks.each_pair do |ch, score| + multi.zrem('failed_checks', "#{existing_name}:#{ch}") + multi.zadd('failed_checks', score, "#{entity_name}:#{ch}") + end - unless current_score.nil? - redis.zrem('current_entities', existing_name) - redis.zadd('current_entities', current_score, entity_name) - end + if rename_all_checks + multi.rename("all_checks:#{existing_name}", "all_checks:#{entity_name}") + end - block_keys.each do |blk| - redis.rename(blk, blk.sub(/^drop_alerts_for_contact:(.+):([^:]+):#{Regexp.escape(existing_name)}:(.+):([^:]+)$/, - "drop_alerts_for_contact:\\1:\\2:#{entity_name}:\\3:\\4")) - end + if rename_current_checks + multi.rename("current_checks:#{existing_name}", "current_checks:#{entity_name}") + end - hashes_to_remove.each {|hash| redis.hdel('checks_by_hash', hash) } - hashes_to_add.each_pair {|hash, chk| redis.hset('checks_by_hash', hash, chk)} + unless current_score.nil? + multi.zrem('current_entities', existing_name) + multi.zadd('current_entities', current_score, entity_name) + end - alerting_to_remove.each_pair do |alerting, chks| - chks.each {|chk| redis.zrem(alerting, chk)} - end + block_keys.each do |blk| + multi.rename(blk, blk.sub(/^drop_alerts_for_contact:(.+):([^:]+):#{Regexp.escape(existing_name)}:(.+):([^:]+)$/, + "drop_alerts_for_contact:\\1:\\2:#{entity_name}:\\3:\\4")) + end - alerting_to_add.each_pair do |alerting, chks| - chks.each_pair {|chk, score| redis.zadd(alerting, score, chk)} - end + hashes_to_remove.each {|hash| multi.hdel('checks_by_hash', hash) } + hashes_to_add.each_pair {|hash, chk| multi.hset('checks_by_hash', hash, chk)} + + alerting_to_remove.each_pair do |alerting, chks| + chks.each {|chk| multi.zrem(alerting, chk)} + end - redis.exec + alerting_to_add.each_pair do |alerting, chks| + chks.each_pair {|chk, score| multi.zadd(alerting, score, chk)} + end + end end # NB only used by the 'entities:reparent' Rake task, but kept in this @@ -213,8 +225,12 @@ def self.merge(old_name, current_name, options = {}) ch_fail_score = redis.zscore("failed_checks", old_check) failed_checks_to_add[current_check] = ch_fail_score unless ch_fail_score.nil? - keys_to_rename["check:#{old_check}"] = "check:#{current_check}" - keys_to_rename[old_states] = new_states + if redis.exists("check:#{old_check}") + keys_to_rename["check:#{old_check}"] = "check:#{current_check}" + end + if redis.exists(old_states) + keys_to_rename[old_states] = new_states + end end notification_types.each do |notif| @@ -229,7 +245,7 @@ def self.merge(old_name, current_name, options = {}) end keys_to_delete << old_notif - else + elsif redis.exists(old_notif) keys_to_rename[old_notif] = new_notif end end @@ -258,13 +274,13 @@ def self.merge(old_name, current_name, options = {}) if redis.exists("all_checks:#{current_name}") keys_to_delete << "all_checks:#{old_name}" - else + elsif redis.exists("all_checks:#{old_name}") keys_to_rename["all_checks:#{old_name}"] = "all_checks:#{current_name}" end if redis.exists("current_checks:#{current_name}") keys_to_delete << "current_checks:#{old_name}" - else + elsif redis.exists("current_checks:#{old_name}") keys_to_rename["current_checks:#{old_name}"] = "current_checks:#{current_name}" end @@ -291,7 +307,7 @@ def self.merge(old_name, current_name, options = {}) if redis.exists(current_actions) action_data[current_actions] = redis.hgetall(old_actions) keys_to_delete << old_actions - else + elsif redis.exists(old_actions) keys_to_rename[old_actions] = current_actions end end @@ -317,7 +333,7 @@ def self.merge(old_name, current_name, options = {}) # TTL < 0 is a redis error code -- key not present, etc. if (old_ttl >= 0) && ((new_ttl < 0) || ((old_time + old_ttl) > (new_time + new_ttl))) - keys_to_rename[maint_key] = new_maint_key + keys_to_rename[maint_key] = new_maint_key if redis.exists(maint_key) maints_to_set[new_maint_key] = redis.zscore("#{maint_key}s", old_time) end @@ -350,84 +366,83 @@ def self.merge(old_name, current_name, options = {}) notif_keys = redis.keys("#{old_name}:*:last_*_notification") - redis.multi + redis.multi do |multi| - check_history_keys.each do |chk| - redis.renamenx(chk, chk.sub(/^#{Regexp.escape(old_name)}:/, "#{current_name}:")) - end - - check_timestamps_keys.each do |ctk| - dest = ctk.sub(/^#{Regexp.escape(old_name)}:/, "#{current_name}:") - redis.zunionstore(dest, [ctk, dest], :aggregate => :max) - end + check_history_keys.each do |chk| + multi.renamenx(chk, chk.sub(/^#{Regexp.escape(old_name)}:/, "#{current_name}:")) + end - all_checks_to_remove.each do |actr| - redis.zrem('all_checks', actr) - end + check_timestamps_keys.each do |ctk| + dest = ctk.sub(/^#{Regexp.escape(old_name)}:/, "#{current_name}:") + multi.zunionstore(dest, [ctk, dest], :aggregate => :max) + end - all_checks_to_add.each_pair do |acta, score| - redis.zadd('all_checks', score, acta) - end + all_checks_to_remove.each do |actr| + multi.zrem('all_checks', actr) + end - failed_checks_to_remove.each do |fctr| - redis.zrem('failed_checks', fctr) - end + all_checks_to_add.each_pair do |acta, score| + multi.zadd('all_checks', score, acta) + end - failed_checks_to_add.each_pair do |fcta, score| - redis.zadd('failed_checks', score, fcta) - end + failed_checks_to_remove.each do |fctr| + multi.zrem('failed_checks', fctr) + end - action_data.each_pair do |action_key, data| - data.each_pair do |k, v| - redis.hsetnx(action_key, k, v) + failed_checks_to_add.each_pair do |fcta, score| + multi.zadd('failed_checks', score, fcta) end - end - redis.zunionstore("current_checks:#{current_name}", - ["current_checks:#{old_name}", "current_checks:#{current_name}"], - :aggregate => :max) + action_data.each_pair do |action_key, data| + data.each_pair do |k, v| + multi.hsetnx(action_key, k, v) + end + end - redis.zrem('current_entities', old_name) - unless old_score.nil? - redis.zadd('current_entities', old_score, current_name) - end + multi.zunionstore("current_checks:#{current_name}", + ["current_checks:#{old_name}", "current_checks:#{current_name}"], + :aggregate => :max) - maints_to_set.each_pair do |maint_key, score| - redis.zadd("#{maint_key}s", score, current_name) - end + multi.zrem('current_entities', old_name) + unless old_score.nil? + multi.zadd('current_entities', old_score, current_name) + end - stored_maint_keys.each do |stored_maint_key| - new_stored_maint_key = stored_maint_key.sub(/^#{Regexp.escape(old_name)}:/, "#{current_name}:") - redis.zunionstore(new_stored_maint_key, - [stored_maint_key, new_stored_maint_key], - :aggregate => :max) - end + maints_to_set.each_pair do |maint_key, score| + multi.zadd("#{maint_key}s", score, current_name) + end - notif_keys.each do |nk| - dest = nk.sub(/^#{Regexp.escape(old_name)}:/, "#{current_name}:") - redis.renamenx(nk, dest) - redis.del(nk) - end + stored_maint_keys.each do |stored_maint_key| + new_stored_maint_key = stored_maint_key.sub(/^#{Regexp.escape(old_name)}:/, "#{current_name}:") + multi.zunionstore(new_stored_maint_key, + [stored_maint_key, new_stored_maint_key], + :aggregate => :max) + end - alerting_to_remove.each_pair do |alerting, chks| - chks.each {|chk| redis.zrem(alerting, chk)} - end + notif_keys.each do |nk| + dest = nk.sub(/^#{Regexp.escape(old_name)}:/, "#{current_name}:") + multi.renamenx(nk, dest) + multi.del(nk) + end - alerting_to_add.each_pair do |alerting, chks| - chks.each_pair {|chk, score| redis.zadd(alerting, score, chk)} - end + alerting_to_remove.each_pair do |alerting, chks| + chks.each {|chk| multi.zrem(alerting, chk)} + end - blocks_to_set.each_pair do |block_key, (timestamp, value)| - redis.setex(block_key, (timestamp - Time.now.to_i), value) - end + alerting_to_add.each_pair do |alerting, chks| + chks.each_pair {|chk, score| multi.zadd(alerting, score, chk)} + end - keys_to_rename.each_pair do |old_key, new_key| - redis.rename(old_key, new_key) - end + blocks_to_set.each_pair do |block_key, (timestamp, value)| + multi.setex(block_key, (timestamp - Time.now.to_i), value) + end - redis.del(*keys_to_delete) unless keys_to_delete.empty? + keys_to_rename.each_pair do |old_key, new_key| + multi.rename(old_key, new_key) + end - redis.exec + multi.del(*keys_to_delete) unless keys_to_delete.empty? + end end # NB: If entities are renamed in imported data before they are @@ -467,10 +482,10 @@ def self.add(entity, options = {}) if redis.hexists('all_entity_ids_by_name', entity_name) merge(existing_name, entity_name, :redis => redis) else - rename(existing_name, entity_name, :redis => redis) { - redis.hdel('all_entity_ids_by_name', existing_name) - redis.hset('all_entity_ids_by_name', entity_name, entity_id) - redis.hset('all_entity_names_by_id', entity_id, entity_name) + rename(existing_name, entity_name, :redis => redis) {|multi| + multi.hdel('all_entity_ids_by_name', existing_name) + multi.hset('all_entity_ids_by_name', entity_name, entity_id) + multi.hset('all_entity_names_by_id', entity_id, entity_name) } end end diff --git a/lib/flapjack/data/entity_check.rb b/lib/flapjack/data/entity_check.rb index 346400879..fad2c33e1 100755 --- a/lib/flapjack/data/entity_check.rb +++ b/lib/flapjack/data/entity_check.rb @@ -609,57 +609,54 @@ def update_state(new_state, options = {}) old_state = self.state - @redis.multi + @redis.multi do |multi| - if old_state != new_state + if old_state != new_state - # Note the current state (for speedy lookups) - @redis.hset("check:#{@key}", 'state', new_state) + # Note the current state (for speedy lookups) + multi.hset("check:#{@key}", 'state', new_state) - # FIXME: rename to last_state_change? - @redis.hset("check:#{@key}", 'last_change', timestamp) + # FIXME: rename to last_state_change? + multi.hset("check:#{@key}", 'last_change', timestamp) - case new_state - when STATE_WARNING, STATE_CRITICAL, STATE_UNKNOWN - @redis.zadd('failed_checks', timestamp, @key) - # FIXME: Iterate through a list of tags associated with an entity:check pair, and update counters - else - @redis.zrem("failed_checks", @key) - # FIXME: Iterate through a list of tags associated with an entity:check pair, and update counters - end + case new_state + when STATE_WARNING, STATE_CRITICAL, STATE_UNKNOWN + multi.zadd('failed_checks', timestamp, @key) + # FIXME: Iterate through a list of tags associated with an entity:check pair, and update counters + else + multi.zrem("failed_checks", @key) + # FIXME: Iterate through a list of tags associated with an entity:check pair, and update counters + end - # Retain event data for entity:check pair - # NB (appending to tail as far as Redis is concerned) - @redis.rpush("#{@key}:states", timestamp) - @redis.set("#{@key}:#{timestamp}:state", new_state) - @redis.set("#{@key}:#{timestamp}:summary", summary) if summary - @redis.set("#{@key}:#{timestamp}:details", details) if details - @redis.set("#{@key}:#{timestamp}:count", count) if count + # Retain event data for entity:check pair + # NB (appending to tail as far as Redis is concerned) + multi.rpush("#{@key}:states", timestamp) + multi.set("#{@key}:#{timestamp}:state", new_state) + multi.set("#{@key}:#{timestamp}:summary", summary) if summary + multi.set("#{@key}:#{timestamp}:details", details) if details + multi.set("#{@key}:#{timestamp}:count", count) if count - @redis.zadd("#{@key}:sorted_state_timestamps", timestamp, timestamp) - end + multi.zadd("#{@key}:sorted_state_timestamps", timestamp, timestamp) + end - # Track when we last saw an event for a particular entity:check pair - self.last_update = timestamp + # Track when we last saw an event for a particular entity:check pair + # (used to be last_update=, but needs to happen in the multi block) + multi.hset("check:#{@key}", 'last_update', timestamp) + multi.zadd("all_checks", timestamp, @key) + multi.zadd("all_checks:#{entity.name}", timestamp, check) + multi.zadd("current_checks:#{entity.name}", timestamp, check) + multi.zadd('current_entities', timestamp, entity.name) + + # Even if this isn't a state change, we need to update the current state + # hash summary and details (as they may have changed) + multi.hset("check:#{@key}", 'summary', (summary || '')) + multi.hset("check:#{@key}", 'details', (details || '')) + if perfdata + multi.hset("check:#{@key}", 'perfdata', format_perfdata(perfdata).to_json) + # multi.set("#{@key}:#{timestamp}:perfdata", perfdata) + end - # Even if this isn't a state change, we need to update the current state - # hash summary and details (as they may have changed) - @redis.hset("check:#{@key}", 'summary', (summary || '')) - @redis.hset("check:#{@key}", 'details', (details || '')) - if perfdata - @redis.hset("check:#{@key}", 'perfdata', format_perfdata(perfdata).to_json) -# @redis.set("#{@key}:#{timestamp}:perfdata", perfdata) end - - @redis.exec - end - - def last_update=(timestamp) - @redis.hset("check:#{@key}", 'last_update', timestamp) - @redis.zadd("all_checks", timestamp, @key) - @redis.zadd("all_checks:#{entity.name}", timestamp, check) - @redis.zadd("current_checks:#{entity.name}", timestamp, check) - @redis.zadd('current_entities', timestamp, entity.name) end def last_update diff --git a/lib/flapjack/data/event.rb b/lib/flapjack/data/event.rb index e51476e9e..ea304e0dc 100755 --- a/lib/flapjack/data/event.rb +++ b/lib/flapjack/data/event.rb @@ -107,10 +107,10 @@ def self.next(queue, opts = {}) # store the raw data in a rejected list rejected_dest = "events_rejected:#{base_time_str}" if options[:archive_events] - redis.multi - redis.lrem(archive_dest, 1, raw) - redis.lpush(rejected_dest, raw) - redis.exec + redis.multi do |multi| + multi.lrem(archive_dest, 1, raw) + multi.lpush(rejected_dest, raw) + end redis.expire(archive_dest, options[:events_archive_maxage]) else redis.lpush(rejected_dest, raw) diff --git a/lib/flapjack/processor.rb b/lib/flapjack/processor.rb index a0658df8d..780ec44c0 100755 --- a/lib/flapjack/processor.rb +++ b/lib/flapjack/processor.rb @@ -191,19 +191,19 @@ def update_keys(event, entity_check, timestamp) event.id_hash = entity_check.ack_hash end - @redis.multi - if event.ok? - @redis.hincrby('event_counters', 'ok', 1) - @redis.hincrby("event_counters:#{@instance_id}", 'ok', 1) - elsif event.failure? - @redis.hincrby('event_counters', 'failure', 1) - @redis.hincrby("event_counters:#{@instance_id}", 'failure', 1) - else - @redis.hincrby('event_counters', 'invalid', 1) - @redis.hincrby("event_counters:#{@instance_id}", 'invalid', 1) - @logger.error("Invalid event received: #{event.inspect}") + @redis.multi do |multi| + if event.ok? + multi.hincrby('event_counters', 'ok', 1) + multi.hincrby("event_counters:#{@instance_id}", 'ok', 1) + elsif event.failure? + multi.hincrby('event_counters', 'failure', 1) + multi.hincrby("event_counters:#{@instance_id}", 'failure', 1) + else + multi.hincrby('event_counters', 'invalid', 1) + multi.hincrby("event_counters:#{@instance_id}", 'invalid', 1) + @logger.error("Invalid event received: #{event.inspect}") + end end - @redis.exec previous_state = entity_check.state @@ -233,14 +233,16 @@ def update_keys(event, entity_check, timestamp) # Action events represent human or automated interaction with Flapjack when 'action' # When an action event is processed, store the event. - @redis.multi - @redis.hset(event.id + ':actions', timestamp, event.state) - @redis.hincrby('event_counters', 'action', 1) - @redis.hincrby("event_counters:#{@instance_id}", 'action', 1) - @redis.exec + @redis.multi do |multi| + multi.hset(event.id + ':actions', timestamp, event.state) + multi.hincrby('event_counters', 'action', 1) + multi.hincrby("event_counters:#{@instance_id}", 'action', 1) + end else - @redis.hincrby('event_counters', 'invalid', 1) - @redis.hincrby("event_counters:#{@instance_id}", 'invalid', 1) + @redis.multi do |multi| + multi.hincrby('event_counters', 'invalid', 1) + multi.hincrby("event_counters:#{@instance_id}", 'invalid', 1) + end @logger.error("Invalid event received: #{event.inspect}") end @@ -251,12 +253,12 @@ def generate_notification(event, entity_check, timestamp, previous_state) notification_type = Flapjack::Data::Notification.type_for_event(event) max_notified_severity = entity_check.max_notified_severity_of_current_failure - @redis.multi - @redis.set("#{event.id}:last_#{notification_type}_notification", timestamp) - @redis.set("#{event.id}:last_#{event.state}_notification", timestamp) if event.failure? - @redis.rpush("#{event.id}:#{notification_type}_notifications", timestamp) - @redis.rpush("#{event.id}:#{event.state}_notifications", timestamp) if event.failure? - @redis.exec + @redis.multi do |multi| + multi.set("#{event.id}:last_#{notification_type}_notification", timestamp) + multi.set("#{event.id}:last_#{event.state}_notification", timestamp) if event.failure? + multi.rpush("#{event.id}:#{notification_type}_notifications", timestamp) + multi.rpush("#{event.id}:#{event.state}_notifications", timestamp) if event.failure? + end @logger.debug("Notification of type #{notification_type} is being generated for #{event.id}: " + event.inspect) diff --git a/spec/lib/flapjack/data/contact_spec.rb b/spec/lib/flapjack/data/contact_spec.rb index a17db067b..102ad16ad 100644 --- a/spec/lib/flapjack/data/contact_spec.rb +++ b/spec/lib/flapjack/data/contact_spec.rb @@ -218,7 +218,12 @@ ec = Flapjack::Data::EntityCheck.for_entity_name(entity_name, 'PING', :redis => @redis) t = Time.now.to_i ec.update_state('ok', :timestamp => t, :summary => 'a') - ec.last_update = t + # was check.last_update= + @redis.hset("check:#{entity_name}:PING", 'last_update', t) + @redis.zadd("all_checks", t, @key) + @redis.zadd("all_checks:#{entity_name}", t, 'PING') + @redis.zadd("current_checks:#{entity_name}", t, 'PING') + @redis.zadd('current_entities', t, entity_name) contact = Flapjack::Data::Contact.find_by_id('c362', :redis => @redis) eandcs = contact.entities(:checks => true) diff --git a/spec/lib/flapjack/data/entity_check_spec.rb b/spec/lib/flapjack/data/entity_check_spec.rb index 0344806c3..09e3cfb67 100644 --- a/spec/lib/flapjack/data/entity_check_spec.rb +++ b/spec/lib/flapjack/data/entity_check_spec.rb @@ -1199,7 +1199,13 @@ it "updates enabled checks" do ts = Time.now.to_i ec = Flapjack::Data::EntityCheck.for_entity_name(name, check, :redis => @redis) - ec.last_update = ts + + # was check.last_update= + @redis.hset("check:#{name}:#{check}", 'last_update', ts) + @redis.zadd("all_checks", ts, @key) + @redis.zadd("all_checks:#{name}", ts, check) + @redis.zadd("current_checks:#{name}", ts, check) + @redis.zadd('current_entities', ts, name) saved_check_ts = @redis.zscore("current_checks:#{name}", check) expect(saved_check_ts).not_to be_nil diff --git a/spec/lib/flapjack/data/event_spec.rb b/spec/lib/flapjack/data/event_spec.rb index fc9b27486..6f1ae41dc 100644 --- a/spec/lib/flapjack/data/event_spec.rb +++ b/spec/lib/flapjack/data/event_spec.rb @@ -6,6 +6,7 @@ let(:entity_name) { 'xyz-example.com' } let(:check) { 'ping' } let(:redis) { double(::Redis) } + let(:multi) { double('multi') } let!(:time) { Time.now} @@ -79,10 +80,9 @@ expect(Flapjack::Data::Migration).to receive(:purge_expired_archive_index).with(:redis => redis) expect(redis).to receive(:sadd). with('known_events_archive_keys', /^events_archive:/) - expect(redis).to receive(:multi) - expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) - expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) - expect(redis).to receive(:exec) + expect(redis).to receive(:multi).and_yield(multi) + expect(multi).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) + expect(multi).to receive(:lpush).with(/^events_rejected:/, bad_event_json) expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, @@ -112,10 +112,9 @@ expect(Flapjack::Data::Migration).to receive(:purge_expired_archive_index).with(:redis => redis) expect(redis).to receive(:sadd). with('known_events_archive_keys', /^events_archive:/) - expect(redis).to receive(:multi) - expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) - expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) - expect(redis).to receive(:exec) + expect(redis).to receive(:multi).and_yield(multi) + expect(multi).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) + expect(multi).to receive(:lpush).with(/^events_rejected:/, bad_event_json) expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, @@ -145,10 +144,9 @@ expect(Flapjack::Data::Migration).to receive(:purge_expired_archive_index).with(:redis => redis) expect(redis).to receive(:sadd). with('known_events_archive_keys', /^events_archive:/) - expect(redis).to receive(:multi) - expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) - expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) - expect(redis).to receive(:exec) + expect(redis).to receive(:multi).and_yield(multi) + expect(multi).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) + expect(multi).to receive(:lpush).with(/^events_rejected:/, bad_event_json) expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, @@ -180,10 +178,9 @@ expect(Flapjack::Data::Migration).to receive(:purge_expired_archive_index).with(:redis => redis) expect(redis).to receive(:sadd). with('known_events_archive_keys', /^events_archive:/) - expect(redis).to receive(:multi) - expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) - expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) - expect(redis).to receive(:exec) + expect(redis).to receive(:multi).and_yield(multi) + expect(multi).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) + expect(multi).to receive(:lpush).with(/^events_rejected:/, bad_event_json) expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, @@ -271,10 +268,9 @@ expect(Flapjack::Data::Migration).to receive(:purge_expired_archive_index).with(:redis => redis) expect(redis).to receive(:sadd). with('known_events_archive_keys', /^events_archive:/) - expect(redis).to receive(:multi) - expect(redis).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) - expect(redis).to receive(:lpush).with(/^events_rejected:/, bad_event_json) - expect(redis).to receive(:exec) + expect(redis).to receive(:multi).and_yield(multi) + expect(multi).to receive(:lrem).with(/^events_archive:/, 1, bad_event_json) + expect(multi).to receive(:lpush).with(/^events_rejected:/, bad_event_json) expect(redis).to receive(:expire) result = Flapjack::Data::Event.next('events', :block => true, diff --git a/tasks/entities.rake b/tasks/entities.rake index b6f4201c1..a34c35b04 100644 --- a/tasks/entities.rake +++ b/tasks/entities.rake @@ -129,10 +129,10 @@ namespace :entities do if id.nil? || entity.nil? id ||= SecureRandom.uuid - redis.multi - redis.hset('all_entity_ids_by_name', name, id) - redis.hset('all_entity_names_by_id', id, name) - redis.exec + redis.multi do + multi.hset('all_entity_ids_by_name', name, id) + multi.hset('all_entity_names_by_id', id, name) + end puts "Set id '#{id}' for entity #{name}'" elsif entity.name.eql?(name) puts "'#{name}' entity already exists with the provided id" From fb27bf0130647ab61b573bf57978510da09adba5 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Sat, 1 Nov 2014 20:31:34 +1030 Subject: [PATCH 58/69] bugfix URI regex, see #696 --- lib/flapjack/gateways/web.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/flapjack/gateways/web.rb b/lib/flapjack/gateways/web.rb index 15c4b32f0..92788c38d 100755 --- a/lib/flapjack/gateways/web.rb +++ b/lib/flapjack/gateways/web.rb @@ -57,7 +57,7 @@ def start @api_url = @config['api_url'] if @api_url - if (@api_url =~ /^#{URI::regexp(%w(http https))}$/).nil? + if URI.regexp(['http', 'https']).match(@api_url).nil? @logger.error "api_url is not a valid http or https URI (#{@api_url}), discarding" @api_url = nil end From 0ada5ed3f4769561f1a430e79542b3c35d528af9 Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Wed, 5 Nov 2014 15:49:20 +1030 Subject: [PATCH 59/69] data migration to work around previous notification rule bug --- lib/flapjack/data/migration.rb | 29 +++++++++++++ lib/flapjack/redis_pool.rb | 2 + spec/lib/flapjack/data/migration_spec.rb | 52 ++++++++++++++++++++++++ spec/lib/flapjack/redis_pool_spec.rb | 1 + 4 files changed, 84 insertions(+) create mode 100644 spec/lib/flapjack/data/migration_spec.rb diff --git a/lib/flapjack/data/migration.rb b/lib/flapjack/data/migration.rb index 48db8cdc9..72e0443b8 100644 --- a/lib/flapjack/data/migration.rb +++ b/lib/flapjack/data/migration.rb @@ -1,5 +1,8 @@ #!/usr/bin/env ruby +require 'flapjack/data/contact' +require 'flapjack/data/entity_check' + require 'flapjack/data/semaphore' module Flapjack @@ -116,6 +119,32 @@ def self.purge_expired_archive_index(options = {}) end end + def self.correct_notification_rule_contact_linkages(options = {}) + raise "Redis connection not set" unless redis = options[:redis] + + logger = options[:logger] + + if redis.exists('corrected_notification_rule_contact_linkages') + return + end + + invalid_notification_rule_keys = redis.keys("notification_rule:*").select {|k| + contact_id = redis.hget(k, 'contact_id') + contact_id.nil? || contact_id.empty? + }.collect {|nrk| nrk.sub(/^notification_rule:/, '') } + + unless invalid_notification_rule_keys.empty? + Flapjack::Data::Contact.all(:redis => redis).each do |contact| + correctable = contact.notification_rule_ids & invalid_notification_rule_keys + next if correctable.empty? + correctable.each {|ck| redis.hset("notification_rule:#{ck}", 'contact_id', contact.id) } + logger.warn "Set contact #{contact.id} for rules #{correctable.join(', ')}" unless logger.nil? + end + end + + redis.set('corrected_notification_rule_contact_linkages', 'true') + end + end end end \ No newline at end of file diff --git a/lib/flapjack/redis_pool.rb b/lib/flapjack/redis_pool.rb index 4cc9d095a..595d4396a 100644 --- a/lib/flapjack/redis_pool.rb +++ b/lib/flapjack/redis_pool.rb @@ -21,6 +21,8 @@ def initialize(opts = {}) logger = opts[:logger] super(:size => @size) { redis = ::Redis.new(config) + Flapjack::Data::Migration.correct_notification_rule_contact_linkages(:redis => redis, + :logger => logger) Flapjack::Data::Migration.migrate_entity_check_data_if_required(:redis => redis, :logger => logger) Flapjack::Data::Migration.refresh_archive_index(:redis => redis) diff --git a/spec/lib/flapjack/data/migration_spec.rb b/spec/lib/flapjack/data/migration_spec.rb new file mode 100644 index 000000000..c0476c865 --- /dev/null +++ b/spec/lib/flapjack/data/migration_spec.rb @@ -0,0 +1,52 @@ +require 'spec_helper' +require 'flapjack/data/migration' +require 'flapjack/data/notification_rule' + +describe Flapjack::Data::Migration, :redis => true do + + it "fixes a notification rule wih no contact association" do + contact = Flapjack::Data::Contact.add( { + 'id' => 'c362', + 'first_name' => 'John', + 'last_name' => 'Johnson', + 'email' => 'johnj@example.com', + 'media' => { + 'pagerduty' => { + 'service_key' => '123456789012345678901234', + 'subdomain' => 'flpjck', + 'username' => 'flapjack', + 'password' => 'very_secure' + }, + }, + }, + :redis => @redis) + + rule = contact.add_notification_rule( + :tags => ["database","physical"], + :entities => ["foo-app-01.example.com"], + :time_restrictions => [], + :unknown_media => [], + :warning_media => ["email"], + :critical_media => ["sms", "email"], + :unknown_blackhole => false, + :warning_blackhole => false, + :critical_blackhole => false + ) + + rule_id = rule.id + + # degrade as the bug had previously + @redis.hset("notification_rule:#{rule.id}", 'contact_id', '') + + rule = Flapjack::Data::NotificationRule.find_by_id(rule_id, :redis => @redis) + expect(rule).not_to be_nil + expect(rule.contact_id).to be_empty + + Flapjack::Data::Migration.correct_notification_rule_contact_linkages(:redis => @redis) + + rule = Flapjack::Data::NotificationRule.find_by_id(rule_id, :redis => @redis) + expect(rule).not_to be_nil + expect(rule.contact_id).to eq(contact.id) + end + +end \ No newline at end of file diff --git a/spec/lib/flapjack/redis_pool_spec.rb b/spec/lib/flapjack/redis_pool_spec.rb index 5d9a177bf..41b865180 100644 --- a/spec/lib/flapjack/redis_pool_spec.rb +++ b/spec/lib/flapjack/redis_pool_spec.rb @@ -12,6 +12,7 @@ redis } expect(::Redis).to receive(:new).exactly(redis_count).times.and_return(*redis_conns) + expect(Flapjack::Data::Migration).to receive(:correct_notification_rule_contact_linkages).exactly(redis_count).times expect(Flapjack::Data::Migration).to receive(:migrate_entity_check_data_if_required).exactly(redis_count).times expect(Flapjack::Data::Migration).to receive(:refresh_archive_index).exactly(redis_count).times From ea50956094fbbb642cef7d841e4a4782283f0f6f Mon Sep 17 00:00:00 2001 From: Ali Graham Date: Wed, 5 Nov 2014 16:08:15 +1030 Subject: [PATCH 60/69] disable perftools.rb, not building on latest 1.9.3-p550 --- Gemfile | 9 +++++---- Gemfile-ruby1.9.lock | 4 ---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Gemfile b/Gemfile index 3eb21c740..663706b6b 100644 --- a/Gemfile +++ b/Gemfile @@ -22,8 +22,9 @@ group :test do gem 'fuubar' gem 'simplecov', :require => false - if RUBY_VERSION.split('.')[0] == '1' && RUBY_VERSION.split('.')[1] == '9' - gem 'debugger-ruby_core_source', '>= 1.3.4' # required for perftools.rb - gem 'perftools.rb' - end + # # Not compiling under 1.9.3-p550 anyway + # if RUBY_VERSION.split('.')[0] == '1' && RUBY_VERSION.split('.')[1] == '9' + # gem 'debugger-ruby_core_source', '>= 1.3.4' # required for perftools.rb + # gem 'perftools.rb' + # end end diff --git a/Gemfile-ruby1.9.lock b/Gemfile-ruby1.9.lock index df43bdaab..09c0a43f7 100644 --- a/Gemfile-ruby1.9.lock +++ b/Gemfile-ruby1.9.lock @@ -62,7 +62,6 @@ GEM multi_test (>= 0.1.1) daemons (1.1.9) dante (0.2.0) - debugger-ruby_core_source (1.3.5) delorean (2.1.0) chronic diff-lcs (1.2.5) @@ -143,7 +142,6 @@ GEM term-ansicolor (~> 1.0) thor webrick - perftools.rb (2.0.1) pry (0.10.1) coderay (~> 1.1.0) method_source (~> 0.8.1) @@ -233,7 +231,6 @@ PLATFORMS DEPENDENCIES async_rack_test (>= 0.0.5) cucumber - debugger-ruby_core_source (>= 1.3.4) delorean flapjack! fuubar @@ -241,7 +238,6 @@ DEPENDENCIES guard-cucumber guard-rspec pact - perftools.rb rack-test rb-fsevent resque_spec From 8e783f1eff97d0c5eccfe8f9b5e35a20765f614e Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Fri, 7 Nov 2014 22:53:03 +1030 Subject: [PATCH 61/69] prepare 1.2.0 release --- CHANGELOG.md | 4 ++++ Gemfile-ruby1.9.lock | 12 ++++++------ Gemfile.lock | 14 +++++++------- lib/flapjack/version.rb | 2 +- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69e0670ea..acc433f83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## Flapjack Changelog +# 1.2.0 - 2014-11-07 +- Bug: multi blocks for safe redis connection pool usage #694 (@ali-graham) +- Bug: data migration to work around previous notification rule bug #699 (@ali-graham) + # 1.2.0rc2 - 2014-10-17 - Feature: Cache entity and check name <-> id lookups #682 (@ali-graham) - Chore: Add last_change field to status_reports in the API (closes: #678) #679 (@Hobbsee) diff --git a/Gemfile-ruby1.9.lock b/Gemfile-ruby1.9.lock index 82ebe4567..2b50ae0e5 100644 --- a/Gemfile-ruby1.9.lock +++ b/Gemfile-ruby1.9.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - flapjack (1.2.0rc2) + flapjack (1.2.0) activesupport (~> 3.2.14) blather (~> 0.8.3) chronic @@ -31,7 +31,7 @@ PATH GEM remote: https://rubygems.org/ specs: - activesupport (3.2.19) + activesupport (3.2.20) i18n (~> 0.6, >= 0.6.4) multi_json (~> 1.0) addressable (2.3.6) @@ -121,10 +121,10 @@ GEM rb-fsevent (>= 0.9.3) rb-inotify (>= 0.9) lumberjack (1.0.9) - mail (2.6.1) + mail (2.6.3) mime-types (>= 1.16, < 3) method_source (0.8.2) - mime-types (2.4.1) + mime-types (2.4.3) mini_portile (0.6.0) msgpack (0.5.9) multi_json (1.10.1) @@ -134,7 +134,7 @@ GEM nokogiri (1.6.2.1) mini_portile (= 0.6.0) numerizer (0.1.1) - oj (2.10.3) + oj (2.11.0) pact (1.3.3) awesome_print (~> 1.1) find_a_port (~> 1.0.1) @@ -219,7 +219,7 @@ GEM tins (1.3.3) trollop (2.0) tzinfo (1.0.1) - tzinfo-data (1.2014.8) + tzinfo-data (1.2014.9) tzinfo (>= 1.0.0) vegas (0.1.11) rack (>= 1.0.0) diff --git a/Gemfile.lock b/Gemfile.lock index 9b50c7d0a..44aa520e7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - flapjack (1.2.0rc2) + flapjack (1.2.0) activesupport (~> 3.2.14) blather (~> 0.8.3) chronic @@ -31,7 +31,7 @@ PATH GEM remote: https://rubygems.org/ specs: - activesupport (3.2.19) + activesupport (3.2.20) i18n (~> 0.6, >= 0.6.4) multi_json (~> 1.0) addressable (2.3.6) @@ -121,12 +121,12 @@ GEM rb-fsevent (>= 0.9.3) rb-inotify (>= 0.9) lumberjack (1.0.9) - mail (2.6.1) + mail (2.6.3) mime-types (>= 1.16, < 3) method_source (0.8.2) - mime-types (2.3) + mime-types (2.4.3) mini_portile (0.6.0) - msgpack (0.5.8) + msgpack (0.5.9) multi_json (1.10.1) multi_test (0.1.1) niceogiri (1.1.2) @@ -134,7 +134,7 @@ GEM nokogiri (1.6.2.1) mini_portile (= 0.6.0) numerizer (0.1.1) - oj (2.10.2) + oj (2.11.0) pact (1.3.3) awesome_print (~> 1.1) find_a_port (~> 1.0.1) @@ -219,7 +219,7 @@ GEM tins (1.3.3) trollop (2.0) tzinfo (1.0.1) - tzinfo-data (1.2014.8) + tzinfo-data (1.2014.9) tzinfo (>= 1.0.0) vegas (0.1.11) rack (>= 1.0.0) diff --git a/lib/flapjack/version.rb b/lib/flapjack/version.rb index a595c1546..2062a2f3f 100644 --- a/lib/flapjack/version.rb +++ b/lib/flapjack/version.rb @@ -1,6 +1,6 @@ #!/usr/bin/env ruby module Flapjack - VERSION = "1.2.0rc2" + VERSION = "1.2.0" end From 97fe51a98ac47415dd403345c9f50c5824f33c89 Mon Sep 17 00:00:00 2001 From: Sarah Kowalik Date: Mon, 24 Nov 2014 12:34:30 +1100 Subject: [PATCH 62/69] Give examples for maintenance command --- lib/flapjack/cli/maintenance.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/flapjack/cli/maintenance.rb b/lib/flapjack/cli/maintenance.rb index fcaecbbc3..0304df11f 100644 --- a/lib/flapjack/cli/maintenance.rb +++ b/lib/flapjack/cli/maintenance.rb @@ -93,13 +93,13 @@ def redis :desc => 'The reason for the maintenance window to occur. This can be a string, or a ruby regex of the form \'Downtime for *\' or \'[[:lower:]]\'' show.flag [:s, 'start', 'started', 'starting'], - :desc => 'The start time for the maintenance window. This should be prefixed with "more than", "less than", "on", "before", or "after", or of the form "between times and time"' + :desc => 'The start time for the maintenance window, eg \'before 10am\'. This should be prefixed with \'more than\', \'less than\', \'on\', \'before\', or \'after\', or of the form \'between times and time\'' show.flag [:d, 'duration'], - :desc => 'The total duration of the maintenance window. This should be prefixed with "more than", "less than", "before, "after" or "equal to", or or of the form "between 3 and 4 hours". This should be an interval' + :desc => 'The total duration of the maintenance window, eg \'equal to 5 hours\'. This should be prefixed with \'more than\', \'less than\', \'before, \'after\' or \'equal to\', or or of the form \'between 3 and 4 hours\'. This should be an interval' show.flag [:f, 'finish', 'finished', 'finishing', 'remain', 'remained', 'remaining', 'end'], - :desc => 'The finishing time for the maintenance window. This should be prefixed with "more than", "less than", "on", "before", or "after", or of the form "between time and time"' + :desc => 'The finishing time for the maintenance window, eg \'more than 1 year from now\'. This should be prefixed with \'more than\', \'less than\', \'on\', \'before\', or \'after\', or of the form \'between time and time\'' show.flag [:st, 'state'], :desc => 'The state that the check is currently in' @@ -131,13 +131,13 @@ def redis :desc => 'The reason for the maintenance window to occur. This can be a string, or a ruby regex of the form \'Downtime for *\' or \'[[:lower:]]\'' delete.flag [:s, 'start', 'started', 'starting'], - :desc => 'The start time for the maintenance window. This should be prefixed with "more than", "less than", "on", "before", or "after", or of the form "between times and time"' + :desc => 'The start time for the maintenance window, eg \'before 10am\'. This should be prefixed with \'more than\', \'less than\', \'on\', \'before\', or \'after\', or of the form \'between times and time\'' delete.flag [:d, 'duration'], - :desc => 'The total duration of the maintenance window. This should be prefixed with "more than", "less than", "before, "after" or "equal to", or or of the form "between 3 and 4 hours". This should be an interval' + :desc => 'The total duration of the maintenance window, eg \'equal to 5 hours\'. This should be prefixed with \'more than\', \'less than\', \'before, \'after\' or \'equal to\', or or of the form \'between 3 and 4 hours\'. This should be an interval' delete.flag [:f, 'finish', 'finished', 'finishing', 'remain', 'remained', 'remaining', 'end'], - :desc => 'The finishing time for the maintenance window. This should be prefixed with "more than", "less than", "on", "before", or "after", or of the form "between time and time"' + :desc => 'The finishing time for the maintenance window, eg \'more than 1 year from now\'. This should be prefixed with \'more than\', \'less than\', \'on\', \'before\', or \'after\', or of the form \'between time and time\'' delete.flag [:st, 'state'], :desc => 'The state that the check is currently in' @@ -167,13 +167,13 @@ def redis :desc => 'The reason for the maintenance window to occur' create.flag [:s, 'start', 'started', 'starting'], - :desc => 'The start time for the maintenance window' + :desc => 'The start time for the maintenance window, eg \'now\' or \'in 3 hours\'' create.flag [:d, 'duration'], - :desc => 'The total duration of the maintenance window. This should be an interval' + :desc => 'The total duration of the maintenance window, eg \'30 minutes\'. This should be an interval' create.flag [:t, 'type'], - :desc => 'The type of maintenance scheduled ("scheduled")', + :desc => 'The type of maintenance scheduled (\'scheduled\')', :default_value => 'scheduled' create.action do |global_options,options,args| From 00efb2ead88c193ce1237ba64bc19ff8becc8bbb Mon Sep 17 00:00:00 2001 From: Sarah Kowalik Date: Mon, 24 Nov 2014 12:48:48 +1100 Subject: [PATCH 63/69] Use GLI's check for required arguments, switch flag order to make error messages clearer --- lib/flapjack/cli/maintenance.rb | 62 ++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/lib/flapjack/cli/maintenance.rb b/lib/flapjack/cli/maintenance.rb index 0304df11f..cdc4a7663 100644 --- a/lib/flapjack/cli/maintenance.rb +++ b/lib/flapjack/cli/maintenance.rb @@ -57,7 +57,6 @@ def delete end def create - exit_now!("Entity & check must be supplied to create a maintenance period") if @options[:entity].nil? || @options[:check].nil? errors = Flapjack::Data::EntityCheck.create_maintenance(@options) (errors.each { |k, v| puts "#{k}: #{v}" }; exit_now!('Failed to create maintenances')) if errors.length > 0 puts "The maintenances specified have been created" @@ -83,28 +82,28 @@ def redis maintenance.desc 'Show maintenance windows according to criteria (default: all ongoing maintenance)' maintenance.command :show do |show| - show.flag [:e, 'entity'], + show.flag ['entity', :e], :desc => 'The entity for the maintenance window to occur on. This can be a string, or a ruby regex of the form \'db*\' or \'[[:lower:]]\'' - show.flag [:c, 'check'], + show.flag ['check', :c], :desc => 'The check for the maintenance window to occur on. This can be a string, or a ruby regex of the form \'http*\' or \'[[:lower:]]\'' - show.flag [:r, 'reason'], + show.flag ['reason', :r], :desc => 'The reason for the maintenance window to occur. This can be a string, or a ruby regex of the form \'Downtime for *\' or \'[[:lower:]]\'' - show.flag [:s, 'start', 'started', 'starting'], + show.flag ['start', 'started', 'starting', :s], :desc => 'The start time for the maintenance window, eg \'before 10am\'. This should be prefixed with \'more than\', \'less than\', \'on\', \'before\', or \'after\', or of the form \'between times and time\'' - show.flag [:d, 'duration'], + show.flag ['duration', :d], :desc => 'The total duration of the maintenance window, eg \'equal to 5 hours\'. This should be prefixed with \'more than\', \'less than\', \'before, \'after\' or \'equal to\', or or of the form \'between 3 and 4 hours\'. This should be an interval' - show.flag [:f, 'finish', 'finished', 'finishing', 'remain', 'remained', 'remaining', 'end'], + show.flag ['finish', 'finished', 'finishing', 'remain', 'remained', 'remaining', 'end', :f], :desc => 'The finishing time for the maintenance window, eg \'more than 1 year from now\'. This should be prefixed with \'more than\', \'less than\', \'on\', \'before\', or \'after\', or of the form \'between time and time\'' - show.flag [:st, 'state'], + show.flag ['state', :st], :desc => 'The state that the check is currently in' - show.flag [:t, 'type'], + show.flag ['type', :t], :desc => 'The type of maintenance scheduled', :default_value => 'scheduled' @@ -117,32 +116,32 @@ def redis maintenance.desc 'Delete maintenance windows according to criteria (default: all ongoing maintenance)' maintenance.command :delete do |delete| - delete.flag [:a, 'apply'], + delete.flag ['apply', :a], :desc => 'Whether this deletion should occur', :default_value => false - delete.flag [:e, 'entity'], + delete.flag ['entity', :e], :desc => 'The entity for the maintenance window to occur on. This can be a string, or a ruby regex of the form \'db*\' or \'[[:lower:]]\'' - delete.flag [:c, 'check'], + delete.flag ['check', :c], :desc => 'The check for the maintenance window to occur on. This can be a string, or a ruby regex of the form \'http*\' or \'[[:lower:]]\'' - delete.flag [:r, 'reason'], + delete.flag ['reason', :r], :desc => 'The reason for the maintenance window to occur. This can be a string, or a ruby regex of the form \'Downtime for *\' or \'[[:lower:]]\'' - delete.flag [:s, 'start', 'started', 'starting'], + delete.flag ['start', 'started', 'starting', :s], :desc => 'The start time for the maintenance window, eg \'before 10am\'. This should be prefixed with \'more than\', \'less than\', \'on\', \'before\', or \'after\', or of the form \'between times and time\'' - delete.flag [:d, 'duration'], + delete.flag ['duration', :d], :desc => 'The total duration of the maintenance window, eg \'equal to 5 hours\'. This should be prefixed with \'more than\', \'less than\', \'before, \'after\' or \'equal to\', or or of the form \'between 3 and 4 hours\'. This should be an interval' - delete.flag [:f, 'finish', 'finished', 'finishing', 'remain', 'remained', 'remaining', 'end'], + delete.flag ['finish', 'finished', 'finishing', 'remain', 'remained', 'remaining', 'end', :f], :desc => 'The finishing time for the maintenance window, eg \'more than 1 year from now\'. This should be prefixed with \'more than\', \'less than\', \'on\', \'before\', or \'after\', or of the form \'between time and time\'' - delete.flag [:st, 'state'], + delete.flag ['state', :st], :desc => 'The state that the check is currently in' - delete.flag [:t, 'type'], + delete.flag ['type', :t], :desc => 'The type of maintenance scheduled', :default_value => 'scheduled' @@ -155,24 +154,29 @@ def redis maintenance.desc 'Create a maintenance window' maintenance.command :create do |create| - create.flag [:e, 'entity'], + create.flag ['entity', :e], :desc => 'The entity for the maintenance window to occur on. This can be a comma separated list', - :type => Array + :type => Array, + :required => true - create.flag [:c, 'check'], + create.flag ['check', :c], :desc => 'The check for the maintenance window to occur on. This can be a comma separated list', - :type => Array + :type => Array, + :required => true - create.flag [:r, 'reason'], - :desc => 'The reason for the maintenance window to occur' + create.flag ['reason', :r], + :desc => 'The reason for the maintenance window to occur', + :required => true - create.flag [:s, 'start', 'started', 'starting'], - :desc => 'The start time for the maintenance window, eg \'now\' or \'in 3 hours\'' + create.flag ['start', 'started', 'starting', :s], + :desc => 'The start time for the maintenance window, eg \'now\' or \'in 3 hours\'', + :required => true - create.flag [:d, 'duration'], - :desc => 'The total duration of the maintenance window, eg \'30 minutes\'. This should be an interval' + create.flag ['duration', :d], + :desc => 'The total duration of the maintenance window, eg \'30 minutes\'. This should be an interval', + :required => true - create.flag [:t, 'type'], + create.flag ['type', :t], :desc => 'The type of maintenance scheduled (\'scheduled\')', :default_value => 'scheduled' From 219a2ab64b92dcb03497da14208843cc23abe26c Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Tue, 25 Nov 2014 07:55:46 +1030 Subject: [PATCH 64/69] add migration for creating entity ids for old entities --- lib/flapjack/data/entity_check.rb | 7 ++-- lib/flapjack/data/migration.rb | 32 ++++++++++++++++++- .../gateways/jsonapi/report_methods.rb | 2 ++ lib/flapjack/redis_pool.rb | 2 ++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/lib/flapjack/data/entity_check.rb b/lib/flapjack/data/entity_check.rb index fad2c33e1..8f5ffbbcf 100755 --- a/lib/flapjack/data/entity_check.rb +++ b/lib/flapjack/data/entity_check.rb @@ -75,8 +75,11 @@ def self.for_entity_name(entity_name, check_name, options = {}) raise "Redis connection not set" unless redis = options[:redis] create_entity = options[:create_entity] logger = options[:logger] + puts("entity_name: #{entity_name.inspect}") + puts("create_entity: #{create_entity.inspect}") entity = Flapjack::Data::Entity.find_by_name(entity_name, :create => create_entity, :logger => logger, :redis => redis) + puts("entity: #{entity.inspect}") self.new(entity, check_name, :logger => logger, :redis => redis) end @@ -983,8 +986,8 @@ def to_jsonapi(opts = {}) def initialize(entity, check, options = {}) raise "Redis connection not set" unless @redis = options[:redis] - raise "Invalid entity" unless @entity = entity - raise "Invalid check" unless @check = check + raise "Invalid entity (#{entity.inspect})" unless @entity = entity + raise "Invalid check (#{check.inspect} on #{entity.inspect})" unless @check = check @key = "#{entity.name}:#{check}" if @redis.zscore("all_checks", @key).nil? timestamp = options[:timestamp] || Time.now.to_i diff --git a/lib/flapjack/data/migration.rb b/lib/flapjack/data/migration.rb index 72e0443b8..601616a23 100644 --- a/lib/flapjack/data/migration.rb +++ b/lib/flapjack/data/migration.rb @@ -30,6 +30,36 @@ def self.obtain_semaphore(resource, options = {}) semaphore end + def self.create_entity_ids_if_required(options = {}) + raise "Redis connection not set" unless redis = options[:redis] + logger = options[:logger] + + semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, :redis => redis) + if semaphore.nil? + unless logger.nil? + logger.fatal "Could not obtain lock for data migration. Ensure that " + + "no other flapjack processes are running that might be executing " + + "migrations, check logs for any exceptions, manually delete the " + + "'#{ENTITY_DATA_MIGRATION}' key from your Flapjack Redis " + + "database and try running Flapjack again." + end + exit + end + + if redis.exists('created_ids_for_old_entities_without_ids') + return + end + logger.warn "Ensuring all entities have ids ..." unless logger.nil? + + Flapjack::Data::EntityCheck.find_current_names_by_entity(:redis => redis, :logger => logger).keys.each {|entity_name| + entity = Flapjack::Data::Entity.find_by_name(entity_name, :create => true, :redis => redis, :logger => logger) + } + + redis.set('created_ids_for_old_entities_without_ids', 'true') + logger.warn "Entity id creation complete." + semaphore.release + end + def self.migrate_entity_check_data_if_required(options = {}) raise "Redis connection not set" unless redis = options[:redis] @@ -147,4 +177,4 @@ def self.correct_notification_rule_contact_linkages(options = {}) end end -end \ No newline at end of file +end diff --git a/lib/flapjack/gateways/jsonapi/report_methods.rb b/lib/flapjack/gateways/jsonapi/report_methods.rb index 6d4ae39a6..c065c6b34 100644 --- a/lib/flapjack/gateways/jsonapi/report_methods.rb +++ b/lib/flapjack/gateways/jsonapi/report_methods.rb @@ -31,6 +31,8 @@ def load_api_data(entity_ids, event_ids, &block) each_with_object([]) do |check_name, memo| en, cn = check_name.split(':', 2) halt(500, 'Malformed check ID') if en.nil? || cn.nil? + logger.debug("Flapjack::Gateways::JSONAPI::ReportMethods::Helpers#load_api_data entity: #{en}, check: #{cn}") + memo << find_entity_check_by_name(en, cn) end elsif !event_ids.empty? diff --git a/lib/flapjack/redis_pool.rb b/lib/flapjack/redis_pool.rb index 595d4396a..693f999fc 100644 --- a/lib/flapjack/redis_pool.rb +++ b/lib/flapjack/redis_pool.rb @@ -25,6 +25,8 @@ def initialize(opts = {}) :logger => logger) Flapjack::Data::Migration.migrate_entity_check_data_if_required(:redis => redis, :logger => logger) + Flapjack::Data::Migration.create_entity_ids_if_required(:redis => redis, + :logger => logger) Flapjack::Data::Migration.refresh_archive_index(:redis => redis) redis } From a4709c40234c4e73029c260dfbf15c9cb8c838dc Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Tue, 25 Nov 2014 10:19:26 +1030 Subject: [PATCH 65/69] fix silly deadlock, make more resilient --- lib/flapjack/data/migration.rb | 126 +++++++++++++++++---------------- 1 file changed, 65 insertions(+), 61 deletions(-) diff --git a/lib/flapjack/data/migration.rb b/lib/flapjack/data/migration.rb index 601616a23..3f704b910 100644 --- a/lib/flapjack/data/migration.rb +++ b/lib/flapjack/data/migration.rb @@ -18,10 +18,10 @@ def self.obtain_semaphore(resource, options = {}) semaphore = nil strikes = 0 begin - semaphore = Flapjack::Data::Semaphore.new(resource, :redis => redis, :expiry => 60) + semaphore = Flapjack::Data::Semaphore.new(resource, :redis => redis, :expiry => 300) rescue Flapjack::Data::Semaphore::ResourceLocked strikes += 1 - if strikes < 5 + if strikes < 10 sleep 2 retry end @@ -34,30 +34,34 @@ def self.create_entity_ids_if_required(options = {}) raise "Redis connection not set" unless redis = options[:redis] logger = options[:logger] - semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, :redis => redis) - if semaphore.nil? - unless logger.nil? - logger.fatal "Could not obtain lock for data migration. Ensure that " + - "no other flapjack processes are running that might be executing " + - "migrations, check logs for any exceptions, manually delete the " + - "'#{ENTITY_DATA_MIGRATION}' key from your Flapjack Redis " + - "database and try running Flapjack again." - end - exit - end - if redis.exists('created_ids_for_old_entities_without_ids') return end - logger.warn "Ensuring all entities have ids ..." unless logger.nil? - Flapjack::Data::EntityCheck.find_current_names_by_entity(:redis => redis, :logger => logger).keys.each {|entity_name| - entity = Flapjack::Data::Entity.find_by_name(entity_name, :create => true, :redis => redis, :logger => logger) - } + begin + semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, :redis => redis) + if semaphore.nil? + unless logger.nil? + logger.fatal "Could not obtain lock for data migration (entity id creation). Ensure that " + + "no other flapjack processes are running that might be executing " + + "migrations, check logs for any exceptions, manually delete the " + + "'#{ENTITY_DATA_MIGRATION}' key from your Flapjack Redis " + + "database and try running Flapjack again." + end + raise "Unable to obtain semaphore #{ENTITY_DATA_MIGRATION}" + end + + logger.warn "Ensuring all entities have ids ..." unless logger.nil? - redis.set('created_ids_for_old_entities_without_ids', 'true') - logger.warn "Entity id creation complete." - semaphore.release + Flapjack::Data::EntityCheck.find_current_names_by_entity(:redis => redis, :logger => logger).keys.each {|entity_name| + entity = Flapjack::Data::Entity.find_by_name(entity_name, :create => true, :redis => redis, :logger => logger) + } + + redis.set('created_ids_for_old_entities_without_ids', 'true') + logger.warn "Entity id creation complete." + ensure + semaphore.release + end end def self.migrate_entity_check_data_if_required(options = {}) @@ -65,61 +69,61 @@ def self.migrate_entity_check_data_if_required(options = {}) logger = options[:logger] - semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, :redis => redis) - if semaphore.nil? - unless logger.nil? - logger.fatal "Could not obtain lock for data migration. Ensure that " + - "no other flapjack processes are running that might be executing " + - "migrations, check logs for any exceptions, manually delete the " + - "'#{ENTITY_DATA_MIGRATION}' key from your Flapjack Redis " + - "database and try running Flapjack again." - end - exit - end - if redis.exists('all_checks') - semaphore.release return end - logger.warn "Upgrading Flapjack's entity/check Redis indexes..." unless logger.nil? + begin + semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, :redis => redis) + if semaphore.nil? + unless logger.nil? + logger.fatal "Could not obtain lock for entity check data migration. Ensure that " + + "no other flapjack processes are running that might be executing " + + "migrations, check logs for any exceptions, manually delete the " + + "'#{ENTITY_DATA_MIGRATION}' key from your Flapjack Redis " + + "database and try running Flapjack again." + end + raise "Unable to obtain semaphore #{ENTITY_DATA_MIGRATION}" + end + + logger.warn "Upgrading Flapjack's entity/check Redis indexes..." unless logger.nil? - check_names = redis.keys('check:*').map {|c| c.sub(/^check:/, '') } | - Flapjack::Data::EntityCheck.find_current_names(:redis => redis) + check_names = redis.keys('check:*').map {|c| c.sub(/^check:/, '') } | + Flapjack::Data::EntityCheck.find_current_names(:redis => redis) - unless check_names.empty? - timestamp = Time.now.to_i + unless check_names.empty? + timestamp = Time.now.to_i - check_names.each do |ecn| - redis.zadd("all_checks", timestamp, ecn) - entity_name, check = ecn.split(':', 2) - redis.zadd("all_checks:#{entity_name}", timestamp, check) - # not deleting the check hashes, they store useful data + check_names.each do |ecn| + redis.zadd("all_checks", timestamp, ecn) + entity_name, check = ecn.split(':', 2) + redis.zadd("all_checks:#{entity_name}", timestamp, check) + # not deleting the check hashes, they store useful data + end end - end - logger.warn "Checks indexed." unless logger.nil? + logger.warn "Checks indexed." unless logger.nil? - entity_name_keys = redis.keys("entity_id:*") - unless entity_name_keys.empty? - ids = redis.mget(*entity_name_keys) + entity_name_keys = redis.keys("entity_id:*") + unless entity_name_keys.empty? + ids = redis.mget(*entity_name_keys) - entity_name_keys.each do |enk| - enk =~ /^entity_id:(.+)$/; entity_name = $1; entity_id = ids.shift + entity_name_keys.each do |enk| + enk =~ /^entity_id:(.+)$/; entity_name = $1; entity_id = ids.shift - redis.hset('all_entity_names_by_id', entity_id, entity_name) - redis.hset('all_entity_ids_by_name', entity_name, entity_id) + redis.hset('all_entity_names_by_id', entity_id, entity_name) + redis.hset('all_entity_ids_by_name', entity_name, entity_id) - redis.del(enk) - redis.del("entity:#{entity_id}") + redis.del(enk) + redis.del("entity:#{entity_id}") + end end - end - - logger.warn "Entities indexed." unless logger.nil? - - semaphore.release - logger.warn "Indexing complete." unless logger.nil? + logger.warn "Entities indexed." unless logger.nil? + logger.warn "Indexing complete." unless logger.nil? + ensure + semaphore.release + end end def self.refresh_archive_index(options = {}) From 5f08eae932e03d4316e460de44fa0e87312d910f Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Tue, 25 Nov 2014 10:26:20 +1030 Subject: [PATCH 66/69] fix specs --- spec/lib/flapjack/redis_pool_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/lib/flapjack/redis_pool_spec.rb b/spec/lib/flapjack/redis_pool_spec.rb index 41b865180..d77cb3987 100644 --- a/spec/lib/flapjack/redis_pool_spec.rb +++ b/spec/lib/flapjack/redis_pool_spec.rb @@ -14,6 +14,7 @@ expect(::Redis).to receive(:new).exactly(redis_count).times.and_return(*redis_conns) expect(Flapjack::Data::Migration).to receive(:correct_notification_rule_contact_linkages).exactly(redis_count).times expect(Flapjack::Data::Migration).to receive(:migrate_entity_check_data_if_required).exactly(redis_count).times + expect(Flapjack::Data::Migration).to receive(:create_entity_ids_if_required).exactly(redis_count).times expect(Flapjack::Data::Migration).to receive(:refresh_archive_index).exactly(redis_count).times frp = Flapjack::RedisPool.new(:size => redis_count) @@ -22,4 +23,4 @@ end end -end \ No newline at end of file +end From a7c3480e158469c346877c61df38fd08518077bd Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Thu, 27 Nov 2014 13:29:24 +1030 Subject: [PATCH 67/69] remove debugging output --- lib/flapjack/data/entity_check.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/flapjack/data/entity_check.rb b/lib/flapjack/data/entity_check.rb index 8f5ffbbcf..514e083ba 100755 --- a/lib/flapjack/data/entity_check.rb +++ b/lib/flapjack/data/entity_check.rb @@ -75,11 +75,8 @@ def self.for_entity_name(entity_name, check_name, options = {}) raise "Redis connection not set" unless redis = options[:redis] create_entity = options[:create_entity] logger = options[:logger] - puts("entity_name: #{entity_name.inspect}") - puts("create_entity: #{create_entity.inspect}") entity = Flapjack::Data::Entity.find_by_name(entity_name, :create => create_entity, :logger => logger, :redis => redis) - puts("entity: #{entity.inspect}") self.new(entity, check_name, :logger => logger, :redis => redis) end From e234a3d3503b9319ed5ea0b87113326253ab3815 Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Thu, 27 Nov 2014 14:41:28 +1030 Subject: [PATCH 68/69] move semaphore acquisition outside begin/ensure block --- lib/flapjack/data/migration.rb | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/flapjack/data/migration.rb b/lib/flapjack/data/migration.rb index 3f704b910..84248b977 100644 --- a/lib/flapjack/data/migration.rb +++ b/lib/flapjack/data/migration.rb @@ -38,19 +38,19 @@ def self.create_entity_ids_if_required(options = {}) return end - begin - semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, :redis => redis) - if semaphore.nil? - unless logger.nil? - logger.fatal "Could not obtain lock for data migration (entity id creation). Ensure that " + - "no other flapjack processes are running that might be executing " + - "migrations, check logs for any exceptions, manually delete the " + - "'#{ENTITY_DATA_MIGRATION}' key from your Flapjack Redis " + - "database and try running Flapjack again." - end - raise "Unable to obtain semaphore #{ENTITY_DATA_MIGRATION}" + semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, :redis => redis) + if semaphore.nil? + unless logger.nil? + logger.fatal "Could not obtain lock for data migration (entity id creation). Ensure that " + + "no other flapjack processes are running that might be executing " + + "migrations, check logs for any exceptions, manually delete the " + + "'#{ENTITY_DATA_MIGRATION}' key from your Flapjack Redis " + + "database and try running Flapjack again." end + raise "Unable to obtain semaphore #{ENTITY_DATA_MIGRATION}" + end + begin logger.warn "Ensuring all entities have ids ..." unless logger.nil? Flapjack::Data::EntityCheck.find_current_names_by_entity(:redis => redis, :logger => logger).keys.each {|entity_name| @@ -73,19 +73,19 @@ def self.migrate_entity_check_data_if_required(options = {}) return end - begin - semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, :redis => redis) - if semaphore.nil? - unless logger.nil? - logger.fatal "Could not obtain lock for entity check data migration. Ensure that " + - "no other flapjack processes are running that might be executing " + - "migrations, check logs for any exceptions, manually delete the " + - "'#{ENTITY_DATA_MIGRATION}' key from your Flapjack Redis " + - "database and try running Flapjack again." - end - raise "Unable to obtain semaphore #{ENTITY_DATA_MIGRATION}" + semaphore = obtain_semaphore(ENTITY_DATA_MIGRATION, :redis => redis) + if semaphore.nil? + unless logger.nil? + logger.fatal "Could not obtain lock for entity check data migration. Ensure that " + + "no other flapjack processes are running that might be executing " + + "migrations, check logs for any exceptions, manually delete the " + + "'#{ENTITY_DATA_MIGRATION}' key from your Flapjack Redis " + + "database and try running Flapjack again." end + raise "Unable to obtain semaphore #{ENTITY_DATA_MIGRATION}" + end + begin logger.warn "Upgrading Flapjack's entity/check Redis indexes..." unless logger.nil? check_names = redis.keys('check:*').map {|c| c.sub(/^check:/, '') } | From 9450d6e50ca0818b7d4cddb0ea9cdff62d347032 Mon Sep 17 00:00:00 2001 From: Jesse Reynolds Date: Thu, 27 Nov 2014 16:05:20 +1030 Subject: [PATCH 69/69] fixes #721 --- lib/flapjack/data/entity_check.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/flapjack/data/entity_check.rb b/lib/flapjack/data/entity_check.rb index 514e083ba..a61ac4458 100755 --- a/lib/flapjack/data/entity_check.rb +++ b/lib/flapjack/data/entity_check.rb @@ -160,7 +160,7 @@ def self.unacknowledged_failing(options = {}) redis.exists(entity_check + ':unscheduled_maintenance') }.collect {|entity_check| Flapjack::Data::EntityCheck.for_event_id(entity_check, :redis => redis) - } + }.compact end def self.find_maintenance(options = {})