lib/outpost/scout.rb in outpost-0.1.0 vs lib/outpost/scout.rb in outpost-0.2.0

- old
+ new

@@ -1,13 +1,71 @@ module Outpost + # Scouts are responsible for gathering data about a something specific that is + # a part of your system. For example, a HTTP Scout is responsible for getting + # the response code (200 for OK, 404 for Page Not Found, etc.), response + # body and any other thing you might want to know. + # + # + # Scouts must also contain expectations. They must be registered into the + # Scout that wish to support different types of expectations. You can supply + # a block or an object that respond to #call and return true if any of the + # rules match. It will receive an instance of the scout (so you can query + # current system state) as the first parameter and the state defined by the + # Outpost as the second. + # + # + # Example: + # expect(:response_code) do |scout, code| + # scout.response_code == code + # end + # + # @example an example of a Scout that parses the HTTP response code + # module Outpost + # module Scouts + # class Http < Outpost::Scout + # expect(:response_code) { |scout,code| scout.response_code == code } + # + # attr_reader :response_code + # + # def setup(options) + # @host = options[:host] + # @port = options[:port] || 80 + # @path = options[:path] || '/' + # end + # + # def execute + # response = Net::HTTP.get_response(@host, @path, @port) + # @response_code = response.code.to_i + # end + # end + # end + # end + # + # @abstract Subclasses must override {#setup} and {#execute} to be a valid + # Scout class Scout class << self + # Returns the hash of expectations, where the key is the name of the + # expectation and the value is the callable Object (object that responds + # to #call) + # + # @return [Hash<Symbol, Object>] def expectations @expectations ? @expectations.dup : [] end + # Registers a new expectation into the Scout. If the callable does not + # respond to #call, an ArgumentError will be raised. + # + # @param [Symbol, #read] expectation The name of the expectation + # (examples: :response_code, :response_time) + # @param [Object, #read] callable An object that responds to call and + # returns a Boolean. It will be executed whenever a Scout is run. + # A block is also accepted. + # @raise [ArgumentError] raised when the callable parameter does not + # respond to #call method. def expect(expectation, callable=nil, &callable_block) callable ||= callable_block if callable.respond_to?(:call) @expectations ||= {} @@ -16,20 +74,36 @@ raise ArgumentError, 'Object must respond to method #call to be a valid expectation.' end end end + # @param [String, #read] description A string containing a description of + # the Scout so it may be identified in the construction of status reports. + # @param [Hash, #read] config A hash containing any number of + # configurations that will be passed to the #setup method def initialize(description, config) @description = description @config = config setup(config.options) end + # Executes the Scout and go through all the registered expectations to find + # out all expectations that match and return the associated status. + # + # @return [Symbol] the current status of the Scout (:up, :down) + # @raise [NotImplementedError] raised when a configured expectation was not + # registered in the Scout. def run statuses = [] execute + # Response_pair contains the expectation as key and the expected value as + # value. + # Example: {:response_time => 200} + # + # status is the status (:up or :down, for example) that will be returned + # in case the expectation match current system status. @config.reports.each do |response_pair, status| response_pair.each do |expectation, value| if self.class.expectations[expectation].nil? message = "expectation '#{expectation}' wasn't implemented by #{self.class.name}" raise NotImplementedError, message @@ -42,13 +116,21 @@ end Report.summarize(statuses) end + # Called when the scout object is being constructed. Arguments can be + # everything the developer set in the creation of Outpost. + # + # @raise [NotImplementedError] raised when method is not overriden. def setup(*args) raise NotImplementedError, 'You must implement the setup method for Scout to work correctly.' end + # Called when the Scout must take action and gather all the data needed to + # be analyzed. + # + # @raise [NotImplementedError] raised when method is not overriden. def execute(*args) raise NotImplementedError, 'You must implement the execute method for Scout to work correctly.' end end