require_relative 'error' require_relative 'check' require_relative 'proc_check' require 'set' module Remon class CheckDsl def initialize(load_paths = []) @load_paths = load_paths @checks = {} end def defcheck(name = nil, &block) return define_klass(&block) if not name name = name.to_s validate_name(name) if @checks[name] raise Error, "check #{name} already defined" end klass = define_klass(&block) klass.name = name @checks[name] = klass end def check(name) name = name.to_s validate_name(name) @checks[name] || load_check(name) end def proc_check(name = nil, &block) ProcCheck.new(name, block) end private def validate_name(name) regex = /\A[a-zA-Z0-9_:]+\z/ if not name =~ regex raise Error, "only alphanumeric, _, : characters allowed for check name" end if name.scan(/:/).size > 1 raise Error, "nested namespacing not allowed in check names" end end def define_klass(&block) Class.new(Check, &block) end def load_file(f) instance_eval File.read(f), f end def load_check(name) file = find_check_file(name) load_file file if a = @checks[name] return a else raise Error, "unable to find check: #{name} in #{file}" end end def find_check_file(name) files = check_files(name) combination = files.product(@load_paths).find { |f, d| Dir.glob("#{d}/#{f}").first } if not combination raise Error, "unable to find check: #{name} in PATH: #{@load_paths.join(":")}" end dir = combination[1] file = combination[0] path = "#{dir}/#{file}" end def check_files(name) files = [] if name.include? ":" part = name.partition(":") namespace = part[0] rest = part[2] files << "#{namespace}/#{rest}.rb" files << "#{namespace}.rb" else files << "#{name}.rb" end files end end end